--- a/NEWS Fri Jun 19 20:22:46 2009 +0200
+++ b/NEWS Fri Jun 19 21:08:07 2009 +0200
@@ -43,6 +43,16 @@
* Constants Set.Pow and Set.image now with authentic syntax; object-logic definitions
Set.Pow_def and Set.image_def. INCOMPATIBILITY.
+* Discontinued ancient tradition to suffix certain ML module names with "_package", e.g.:
+
+ DatatypePackage ~> Datatype
+ InductivePackage ~> Inductive
+
+ etc.
+
+INCOMPATIBILITY.
+
+
* NewNumberTheory: Jeremy Avigad's new version of part of NumberTheory.
If possible, use NewNumberTheory, not NumberTheory.
--- a/src/HOL/FunDef.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/FunDef.thy Fri Jun 19 21:08:07 2009 +0200
@@ -17,7 +17,7 @@
("Tools/function_package/sum_tree.ML")
("Tools/function_package/mutual.ML")
("Tools/function_package/pattern_split.ML")
- ("Tools/function_package/fundef_package.ML")
+ ("Tools/function_package/fundef.ML")
("Tools/function_package/auto_term.ML")
("Tools/function_package/measure_functions.ML")
("Tools/function_package/lexicographic_order.ML")
@@ -112,12 +112,12 @@
use "Tools/function_package/mutual.ML"
use "Tools/function_package/pattern_split.ML"
use "Tools/function_package/auto_term.ML"
-use "Tools/function_package/fundef_package.ML"
+use "Tools/function_package/fundef.ML"
use "Tools/function_package/fundef_datatype.ML"
use "Tools/function_package/induction_scheme.ML"
setup {*
- FundefPackage.setup
+ Fundef.setup
#> FundefDatatype.setup
#> InductionScheme.setup
*}
--- a/src/HOL/Hilbert_Choice.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Hilbert_Choice.thy Fri Jun 19 21:08:07 2009 +0200
@@ -7,7 +7,7 @@
theory Hilbert_Choice
imports Nat Wellfounded Plain
-uses ("Tools/meson.ML") ("Tools/specification_package.ML")
+uses ("Tools/meson.ML") ("Tools/choice_specification.ML")
begin
subsection {* Hilbert's epsilon *}
@@ -596,7 +596,7 @@
lemma exE_some: "[| Ex P ; c == Eps P |] ==> P c"
by (simp only: someI_ex)
-use "Tools/specification_package.ML"
+use "Tools/choice_specification.ML"
end
--- a/src/HOL/HoareParallel/OG_Syntax.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/HoareParallel/OG_Syntax.thy Fri Jun 19 21:08:07 2009 +0200
@@ -95,7 +95,7 @@
| annbexp_tr' _ _ = raise Match;
fun upd_tr' (x_upd, T) =
- (case try (unsuffix RecordPackage.updateN) x_upd of
+ (case try (unsuffix Record.updateN) x_upd of
SOME x => (x, if T = dummyT then T else Term.domain_type T)
| NONE => raise Match);
--- a/src/HOL/HoareParallel/RG_Syntax.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/HoareParallel/RG_Syntax.thy Fri Jun 19 21:08:07 2009 +0200
@@ -68,7 +68,7 @@
| bexp_tr' _ _ = raise Match;
fun upd_tr' (x_upd, T) =
- (case try (unsuffix RecordPackage.updateN) x_upd of
+ (case try (unsuffix Record.updateN) x_upd of
SOME x => (x, if T = dummyT then T else Term.domain_type T)
| NONE => raise Match);
--- a/src/HOL/Imperative_HOL/Heap_Monad.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Imperative_HOL/Heap_Monad.thy Fri Jun 19 21:08:07 2009 +0200
@@ -318,7 +318,7 @@
val dummy_case_term = IVar dummy_name;
(*assumption: dummy values are not relevant for serialization*)
val unitt = IConst (unit', (([], []), []));
- fun dest_abs ((v, ty) `|-> t, _) = ((v, ty), t)
+ fun dest_abs ((v, ty) `|=> t, _) = ((v, ty), t)
| dest_abs (t, ty) =
let
val vs = Code_Thingol.fold_varnames cons t [];
@@ -337,7 +337,7 @@
then tr_bind' [(x1, ty1), (x2, ty2)]
else force t
| _ => force t;
- in (dummy_name, dummy_type) `|-> ICase (((IVar dummy_name, dummy_type),
+ in (dummy_name, dummy_type) `|=> ICase (((IVar dummy_name, dummy_type),
[(unitt, tr_bind' ts)]), dummy_case_term) end
and imp_monad_bind' bind' return' unit' (const as (c, (_, tys))) ts = if c = bind' then case (ts, tys)
of ([t1, t2], ty1 :: ty2 :: _) => imp_monad_bind'' bind' return' unit' [(t1, ty1), (t2, ty2)]
@@ -349,7 +349,7 @@
| imp_monad_bind bind' return' unit' (t as _ `$ _) = (case unfold_app t
of (IConst const, ts) => imp_monad_bind' bind' return' unit' const ts
| (t, ts) => imp_monad_bind bind' return' unit' t `$$ map (imp_monad_bind bind' return' unit') ts)
- | imp_monad_bind bind' return' unit' (v_ty `|-> t) = v_ty `|-> imp_monad_bind bind' return' unit' t
+ | imp_monad_bind bind' return' unit' (v_ty `|=> t) = v_ty `|=> imp_monad_bind bind' return' unit' t
| imp_monad_bind bind' return' unit' (ICase (((t, ty), pats), t0)) = ICase
(((imp_monad_bind bind' return' unit' t, ty), (map o pairself) (imp_monad_bind bind' return' unit') pats), imp_monad_bind bind' return' unit' t0);
--- a/src/HOL/Import/HOL4Setup.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Import/HOL4Setup.thy Fri Jun 19 21:08:07 2009 +0200
@@ -1,10 +1,9 @@
(* Title: HOL/Import/HOL4Setup.thy
- ID: $Id$
Author: Sebastian Skalberg (TU Muenchen)
*)
theory HOL4Setup imports MakeEqual ImportRecorder
- uses ("proof_kernel.ML") ("replay.ML") ("hol4rews.ML") ("import_package.ML") begin
+ uses ("proof_kernel.ML") ("replay.ML") ("hol4rews.ML") ("import.ML") begin
section {* General Setup *}
@@ -162,8 +161,8 @@
use "proof_kernel.ML"
use "replay.ML"
-use "import_package.ML"
+use "import.ML"
-setup ImportPackage.setup
+setup Import.setup
end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Import/import.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,71 @@
+(* Title: HOL/Import/import.ML
+ Author: Sebastian Skalberg (TU Muenchen)
+*)
+
+signature IMPORT =
+sig
+ val debug : bool ref
+ val import_tac : Proof.context -> string * string -> tactic
+ val setup : theory -> theory
+end
+
+structure ImportData = TheoryDataFun
+(
+ type T = ProofKernel.thm option array option
+ val empty = NONE
+ val copy = I
+ val extend = I
+ fun merge _ _ = NONE
+)
+
+structure Import :> IMPORT =
+struct
+
+val debug = ref false
+fun message s = if !debug then writeln s else ()
+
+fun import_tac ctxt (thyname, thmname) =
+ if ! quick_and_dirty
+ then SkipProof.cheat_tac (ProofContext.theory_of ctxt)
+ else
+ fn th =>
+ let
+ val thy = ProofContext.theory_of ctxt
+ val prem = hd (prems_of th)
+ val _ = message ("Import_tac: thyname=" ^ thyname ^ ", thmname=" ^ thmname)
+ val _ = message ("Import trying to prove " ^ Syntax.string_of_term ctxt prem)
+ val int_thms = case ImportData.get thy of
+ NONE => fst (Replay.setup_int_thms thyname thy)
+ | SOME a => a
+ val proof = snd (ProofKernel.import_proof thyname thmname thy) thy
+ val hol4thm = snd (Replay.replay_proof int_thms thyname thmname proof thy)
+ val thm = snd (ProofKernel.to_isa_thm hol4thm)
+ val rew = ProofKernel.rewrite_hol4_term (concl_of thm) thy
+ val thm = equal_elim rew thm
+ val prew = ProofKernel.rewrite_hol4_term prem thy
+ val prem' = #2 (Logic.dest_equals (prop_of prew))
+ val _ = message ("Import proved " ^ Display.string_of_thm thm)
+ val thm = ProofKernel.disambiguate_frees thm
+ val _ = message ("Disambiguate: " ^ Display.string_of_thm thm)
+ in
+ case Shuffler.set_prop thy prem' [("",thm)] of
+ SOME (_,thm) =>
+ let
+ val _ = if prem' aconv (prop_of thm)
+ then message "import: Terms match up"
+ else message "import: Terms DO NOT match up"
+ val thm' = equal_elim (symmetric prew) thm
+ val res = bicompose true (false,thm',0) 1 th
+ in
+ res
+ end
+ | NONE => (message "import: set_prop didn't succeed"; no_tac th)
+ end
+
+val setup = Method.setup @{binding import}
+ (Scan.lift (Args.name -- Args.name) >>
+ (fn arg => fn ctxt => SIMPLE_METHOD (import_tac ctxt arg)))
+ "import HOL4 theorem"
+
+end
+
--- a/src/HOL/Import/import_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-(* Title: HOL/Import/import_package.ML
- Author: Sebastian Skalberg (TU Muenchen)
-*)
-
-signature IMPORT_PACKAGE =
-sig
- val debug : bool ref
- val import_tac : Proof.context -> string * string -> tactic
- val setup : theory -> theory
-end
-
-structure ImportData = TheoryDataFun
-(
- type T = ProofKernel.thm option array option
- val empty = NONE
- val copy = I
- val extend = I
- fun merge _ _ = NONE
-)
-
-structure ImportPackage :> IMPORT_PACKAGE =
-struct
-
-val debug = ref false
-fun message s = if !debug then writeln s else ()
-
-fun import_tac ctxt (thyname, thmname) =
- if ! quick_and_dirty
- then SkipProof.cheat_tac (ProofContext.theory_of ctxt)
- else
- fn th =>
- let
- val thy = ProofContext.theory_of ctxt
- val prem = hd (prems_of th)
- val _ = message ("Import_tac: thyname=" ^ thyname ^ ", thmname=" ^ thmname)
- val _ = message ("Import trying to prove " ^ Syntax.string_of_term ctxt prem)
- val int_thms = case ImportData.get thy of
- NONE => fst (Replay.setup_int_thms thyname thy)
- | SOME a => a
- val proof = snd (ProofKernel.import_proof thyname thmname thy) thy
- val hol4thm = snd (Replay.replay_proof int_thms thyname thmname proof thy)
- val thm = snd (ProofKernel.to_isa_thm hol4thm)
- val rew = ProofKernel.rewrite_hol4_term (concl_of thm) thy
- val thm = equal_elim rew thm
- val prew = ProofKernel.rewrite_hol4_term prem thy
- val prem' = #2 (Logic.dest_equals (prop_of prew))
- val _ = message ("Import proved " ^ Display.string_of_thm thm)
- val thm = ProofKernel.disambiguate_frees thm
- val _ = message ("Disambiguate: " ^ Display.string_of_thm thm)
- in
- case Shuffler.set_prop thy prem' [("",thm)] of
- SOME (_,thm) =>
- let
- val _ = if prem' aconv (prop_of thm)
- then message "import: Terms match up"
- else message "import: Terms DO NOT match up"
- val thm' = equal_elim (symmetric prew) thm
- val res = bicompose true (false,thm',0) 1 th
- in
- res
- end
- | NONE => (message "import: set_prop didn't succeed"; no_tac th)
- end
-
-val setup = Method.setup @{binding import}
- (Scan.lift (Args.name -- Args.name) >>
- (fn arg => fn ctxt => SIMPLE_METHOD (import_tac ctxt arg)))
- "import HOL4 theorem"
-
-end
-
--- a/src/HOL/Import/proof_kernel.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Import/proof_kernel.ML Fri Jun 19 21:08:07 2009 +0200
@@ -2021,7 +2021,7 @@
snd (get_defname thyname name thy)) thy1 names
fun new_name name = fst (get_defname thyname name thy1)
val names' = map (fn name => (new_name name,name,false)) names
- val (thy',res) = SpecificationPackage.add_specification NONE
+ val (thy',res) = Choice_Specification.add_specification NONE
names'
(thy1,th)
val _ = ImportRecorder.add_specification names' th
@@ -2091,7 +2091,7 @@
val tsyn = mk_syn thy tycname
val typ = (tycname,tnames,tsyn)
val ((_, typedef_info), thy') =
- TypedefPackage.add_typedef false (SOME (Binding.name thmname))
+ Typedef.add_typedef false (SOME (Binding.name thmname))
(Binding.name tycname, tnames, tsyn) c NONE (rtac th2 1) thy
val _ = ImportRecorder.add_typedef (SOME thmname) typ c NONE th2
@@ -2179,7 +2179,7 @@
val tsyn = mk_syn thy tycname
val typ = (tycname,tnames,tsyn)
val ((_, typedef_info), thy') =
- TypedefPackage.add_typedef false NONE (Binding.name tycname,tnames,tsyn) c
+ Typedef.add_typedef false NONE (Binding.name tycname,tnames,tsyn) c
(SOME(Binding.name rep_name,Binding.name abs_name)) (rtac th2 1) thy
val _ = ImportRecorder.add_typedef NONE typ c (SOME(rep_name,abs_name)) th2
val fulltyname = Sign.intern_type thy' tycname
--- a/src/HOL/Import/replay.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Import/replay.ML Fri Jun 19 21:08:07 2009 +0200
@@ -329,7 +329,7 @@
and rp (ThmEntry (thyname', thmname', aborted, History history)) thy = rps history thy
| rp (DeltaEntry ds) thy = fold delta ds thy
and delta (Specification (names, th)) thy =
- fst (SpecificationPackage.add_specification NONE names (thy,th_of thy th))
+ fst (Choice_Specification.add_specification NONE names (thy,th_of thy th))
| delta (Hol_mapping (thyname, thmname, isaname)) thy =
add_hol4_mapping thyname thmname isaname thy
| delta (Hol_pending (thyname, thmname, th)) thy =
@@ -344,7 +344,7 @@
| delta (Hol_theorem (thyname, thmname, th)) thy =
add_hol4_theorem thyname thmname ([], th_of thy th) thy
| delta (Typedef (thmname, (t, vs, mx), c, repabs, th)) thy =
- snd (TypedefPackage.add_typedef false (Option.map Binding.name thmname) (Binding.name t, vs, mx) c
+ snd (Typedef.add_typedef false (Option.map Binding.name thmname) (Binding.name t, vs, mx) c
(Option.map (pairself Binding.name) repabs) (rtac (th_of thy th) 1) thy)
| delta (Hol_type_mapping (thyname, tycname, fulltyname)) thy =
add_hol4_type_mapping thyname tycname true fulltyname thy
--- a/src/HOL/Inductive.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Inductive.thy Fri Jun 19 21:08:07 2009 +0200
@@ -7,7 +7,7 @@
theory Inductive
imports Lattices Sum_Type
uses
- ("Tools/inductive_package.ML")
+ ("Tools/inductive.ML")
"Tools/dseq.ML"
("Tools/inductive_codegen.ML")
("Tools/datatype_package/datatype_aux.ML")
@@ -15,9 +15,9 @@
("Tools/datatype_package/datatype_rep_proofs.ML")
("Tools/datatype_package/datatype_abs_proofs.ML")
("Tools/datatype_package/datatype_case.ML")
- ("Tools/datatype_package/datatype_package.ML")
- ("Tools/old_primrec_package.ML")
- ("Tools/primrec_package.ML")
+ ("Tools/datatype_package/datatype.ML")
+ ("Tools/old_primrec.ML")
+ ("Tools/primrec.ML")
("Tools/datatype_package/datatype_codegen.ML")
begin
@@ -320,8 +320,8 @@
val le_fun_def = @{thm le_fun_def} RS @{thm eq_reflection}
*}
-use "Tools/inductive_package.ML"
-setup InductivePackage.setup
+use "Tools/inductive.ML"
+setup Inductive.setup
theorems [mono] =
imp_refl disj_mono conj_mono ex_mono all_mono if_bool_eq_conj
@@ -340,11 +340,11 @@
use "Tools/datatype_package/datatype_rep_proofs.ML"
use "Tools/datatype_package/datatype_abs_proofs.ML"
use "Tools/datatype_package/datatype_case.ML"
-use "Tools/datatype_package/datatype_package.ML"
-setup DatatypePackage.setup
+use "Tools/datatype_package/datatype.ML"
+setup Datatype.setup
-use "Tools/old_primrec_package.ML"
-use "Tools/primrec_package.ML"
+use "Tools/old_primrec.ML"
+use "Tools/primrec.ML"
use "Tools/datatype_package/datatype_codegen.ML"
setup DatatypeCodegen.setup
@@ -364,7 +364,7 @@
fun fun_tr ctxt [cs] =
let
val x = Free (Name.variant (Term.add_free_names cs []) "x", dummyT);
- val ft = DatatypeCase.case_tr true DatatypePackage.datatype_of_constr
+ val ft = DatatypeCase.case_tr true Datatype.datatype_of_constr
ctxt [x, cs]
in lambda x ft end
in [("_lam_pats_syntax", fun_tr)] end
--- a/src/HOL/IsaMakefile Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/IsaMakefile Fri Jun 19 21:08:07 2009 +0200
@@ -146,7 +146,7 @@
Tools/datatype_package/datatype_aux.ML \
Tools/datatype_package/datatype_case.ML \
Tools/datatype_package/datatype_codegen.ML \
- Tools/datatype_package/datatype_package.ML \
+ Tools/datatype_package/datatype.ML \
Tools/datatype_package/datatype_prop.ML \
Tools/datatype_package/datatype_realizer.ML \
Tools/datatype_package/datatype_rep_proofs.ML \
@@ -159,7 +159,7 @@
Tools/function_package/fundef_core.ML \
Tools/function_package/fundef_datatype.ML \
Tools/function_package/fundef_lib.ML \
- Tools/function_package/fundef_package.ML \
+ Tools/function_package/fundef.ML \
Tools/function_package/induction_scheme.ML \
Tools/function_package/inductive_wrap.ML \
Tools/function_package/lexicographic_order.ML \
@@ -172,24 +172,24 @@
Tools/function_package/sum_tree.ML \
Tools/function_package/termination.ML \
Tools/inductive_codegen.ML \
- Tools/inductive_package.ML \
+ Tools/inductive.ML \
Tools/inductive_realizer.ML \
- Tools/inductive_set_package.ML \
+ Tools/inductive_set.ML \
Tools/lin_arith.ML \
Tools/nat_arith.ML \
- Tools/old_primrec_package.ML \
- Tools/primrec_package.ML \
+ Tools/old_primrec.ML \
+ Tools/primrec.ML \
Tools/prop_logic.ML \
- Tools/record_package.ML \
+ Tools/record.ML \
Tools/refute.ML \
Tools/refute_isar.ML \
Tools/rewrite_hol_proof.ML \
Tools/sat_funcs.ML \
Tools/sat_solver.ML \
Tools/split_rule.ML \
- Tools/typecopy_package.ML \
+ Tools/typecopy.ML \
Tools/typedef_codegen.ML \
- Tools/typedef_package.ML \
+ Tools/typedef.ML \
Transitive_Closure.thy \
Typedef.thy \
Wellfounded.thy \
@@ -251,13 +251,13 @@
Tools/Qelim/generated_cooper.ML \
Tools/Qelim/presburger.ML \
Tools/Qelim/qelim.ML \
- Tools/recdef_package.ML \
+ Tools/recdef.ML \
Tools/res_atp.ML \
Tools/res_axioms.ML \
Tools/res_clause.ML \
Tools/res_hol_clause.ML \
Tools/res_reconstruct.ML \
- Tools/specification_package.ML \
+ Tools/choice_specification.ML \
Tools/string_code.ML \
Tools/string_syntax.ML \
Tools/TFL/casesplit.ML \
@@ -424,7 +424,7 @@
IMPORTER_FILES = Import/lazy_seq.ML Import/proof_kernel.ML Import/replay.ML \
Import/shuffler.ML Import/MakeEqual.thy Import/HOL4Setup.thy \
Import/HOL4Syntax.thy Import/HOL4Compat.thy Import/import_syntax.ML \
- Import/hol4rews.ML Import/import_package.ML Import/ROOT.ML
+ Import/hol4rews.ML Import/import.ML Import/ROOT.ML
IMPORTER_HOLLIGHT_FILES = Import/proof_kernel.ML Import/replay.ML \
Import/shuffler.ML Import/MakeEqual.thy Import/HOL4Setup.thy \
@@ -981,7 +981,7 @@
Nominal/nominal_induct.ML \
Nominal/nominal_inductive.ML \
Nominal/nominal_inductive2.ML \
- Nominal/nominal_package.ML \
+ Nominal/nominal.ML \
Nominal/nominal_permeq.ML \
Nominal/nominal_primrec.ML \
Nominal/nominal_thmdecls.ML \
--- a/src/HOL/Isar_examples/Hoare.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Isar_examples/Hoare.thy Fri Jun 19 21:08:07 2009 +0200
@@ -260,7 +260,7 @@
| bexp_tr' _ _ = raise Match;
fun upd_tr' (x_upd, T) =
- (case try (unsuffix RecordPackage.updateN) x_upd of
+ (case try (unsuffix Record.updateN) x_upd of
SOME x => (x, if T = dummyT then T else Term.domain_type T)
| NONE => raise Match);
--- a/src/HOL/List.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/List.thy Fri Jun 19 21:08:07 2009 +0200
@@ -363,7 +363,7 @@
val case2 = Syntax.const "_case1" $ Syntax.const Term.dummy_patternN
$ NilC;
val cs = Syntax.const "_case2" $ case1 $ case2
- val ft = DatatypeCase.case_tr false DatatypePackage.datatype_of_constr
+ val ft = DatatypeCase.case_tr false Datatype.datatype_of_constr
ctxt [x, cs]
in lambda x ft end;
--- a/src/HOL/Nominal/Nominal.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Nominal/Nominal.thy Fri Jun 19 21:08:07 2009 +0200
@@ -3,7 +3,7 @@
uses
("nominal_thmdecls.ML")
("nominal_atoms.ML")
- ("nominal_package.ML")
+ ("nominal.ML")
("nominal_induct.ML")
("nominal_permeq.ML")
("nominal_fresh_fun.ML")
@@ -3670,7 +3670,7 @@
lemma allE_Nil: assumes "\<forall>x. P x" obtains "P []"
using assms ..
-use "nominal_package.ML"
+use "nominal.ML"
(******************************************************)
(* primitive recursive functions on nominal datatypes *)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Nominal/nominal.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,2095 @@
+(* Title: HOL/Nominal/nominal.ML
+ Author: Stefan Berghofer and Christian Urban, TU Muenchen
+
+Nominal datatype package for Isabelle/HOL.
+*)
+
+signature NOMINAL =
+sig
+ val add_nominal_datatype : DatatypeAux.datatype_config -> string list ->
+ (string list * bstring * mixfix *
+ (bstring * string list * mixfix) list) list -> theory -> theory
+ type descr
+ type nominal_datatype_info
+ val get_nominal_datatypes : theory -> nominal_datatype_info Symtab.table
+ val get_nominal_datatype : theory -> string -> nominal_datatype_info option
+ val mk_perm: typ list -> term -> term -> term
+ val perm_of_pair: term * term -> term
+ val mk_not_sym: thm list -> thm list
+ val perm_simproc: simproc
+ val fresh_const: typ -> typ -> term
+ val fresh_star_const: typ -> typ -> term
+end
+
+structure Nominal : NOMINAL =
+struct
+
+val finite_emptyI = thm "finite.emptyI";
+val finite_Diff = thm "finite_Diff";
+val finite_Un = thm "finite_Un";
+val Un_iff = thm "Un_iff";
+val In0_eq = thm "In0_eq";
+val In1_eq = thm "In1_eq";
+val In0_not_In1 = thm "In0_not_In1";
+val In1_not_In0 = thm "In1_not_In0";
+val Un_assoc = thm "Un_assoc";
+val Collect_disj_eq = thm "Collect_disj_eq";
+val empty_def = thm "empty_def";
+val empty_iff = thm "empty_iff";
+
+open DatatypeAux;
+open NominalAtoms;
+
+(** FIXME: Datatype should export this function **)
+
+local
+
+fun dt_recs (DtTFree _) = []
+ | dt_recs (DtType (_, dts)) = List.concat (map dt_recs dts)
+ | dt_recs (DtRec i) = [i];
+
+fun dt_cases (descr: descr) (_, args, constrs) =
+ let
+ fun the_bname i = Long_Name.base_name (#1 (valOf (AList.lookup (op =) descr i)));
+ val bnames = map the_bname (distinct op = (List.concat (map dt_recs args)));
+ in map (fn (c, _) => space_implode "_" (Long_Name.base_name c :: bnames)) constrs end;
+
+
+fun induct_cases descr =
+ DatatypeProp.indexify_names (List.concat (map (dt_cases descr) (map #2 descr)));
+
+fun exhaust_cases descr i = dt_cases descr (valOf (AList.lookup (op =) descr i));
+
+in
+
+fun mk_case_names_induct descr = RuleCases.case_names (induct_cases descr);
+
+fun mk_case_names_exhausts descr new =
+ map (RuleCases.case_names o exhaust_cases descr o #1)
+ (List.filter (fn ((_, (name, _, _))) => name mem_string new) descr);
+
+end;
+
+(* theory data *)
+
+type descr = (int * (string * dtyp list * (string * (dtyp list * dtyp) list) list)) list;
+
+type nominal_datatype_info =
+ {index : int,
+ descr : descr,
+ sorts : (string * sort) list,
+ rec_names : string list,
+ rec_rewrites : thm list,
+ induction : thm,
+ distinct : thm list,
+ inject : thm list};
+
+structure NominalDatatypesData = TheoryDataFun
+(
+ type T = nominal_datatype_info Symtab.table;
+ val empty = Symtab.empty;
+ val copy = I;
+ val extend = I;
+ fun merge _ tabs : T = Symtab.merge (K true) tabs;
+);
+
+val get_nominal_datatypes = NominalDatatypesData.get;
+val put_nominal_datatypes = NominalDatatypesData.put;
+val map_nominal_datatypes = NominalDatatypesData.map;
+val get_nominal_datatype = Symtab.lookup o get_nominal_datatypes;
+
+
+(**** make datatype info ****)
+
+fun make_dt_info descr sorts induct reccomb_names rec_thms
+ (((i, (_, (tname, _, _))), distinct), inject) =
+ (tname,
+ {index = i,
+ descr = descr,
+ sorts = sorts,
+ rec_names = reccomb_names,
+ rec_rewrites = rec_thms,
+ induction = induct,
+ distinct = distinct,
+ inject = inject});
+
+(*******************************)
+
+val (_ $ (_ $ (_ $ (distinct_f $ _) $ _))) = hd (prems_of distinct_lemma);
+
+
+(** simplification procedure for sorting permutations **)
+
+val dj_cp = thm "dj_cp";
+
+fun dest_permT (Type ("fun", [Type ("List.list", [Type ("*", [T, _])]),
+ Type ("fun", [_, U])])) = (T, U);
+
+fun permTs_of (Const ("Nominal.perm", T) $ t $ u) = fst (dest_permT T) :: permTs_of u
+ | permTs_of _ = [];
+
+fun perm_simproc' thy ss (Const ("Nominal.perm", T) $ t $ (u as Const ("Nominal.perm", U) $ r $ s)) =
+ let
+ val (aT as Type (a, []), S) = dest_permT T;
+ val (bT as Type (b, []), _) = dest_permT U
+ in if aT mem permTs_of u andalso aT <> bT then
+ let
+ val cp = cp_inst_of thy a b;
+ val dj = dj_thm_of thy b a;
+ val dj_cp' = [cp, dj] MRS dj_cp;
+ val cert = SOME o cterm_of thy
+ in
+ SOME (mk_meta_eq (Drule.instantiate' [SOME (ctyp_of thy S)]
+ [cert t, cert r, cert s] dj_cp'))
+ end
+ else NONE
+ end
+ | perm_simproc' thy ss _ = NONE;
+
+val perm_simproc =
+ Simplifier.simproc (the_context ()) "perm_simp" ["pi1 \<bullet> (pi2 \<bullet> x)"] perm_simproc';
+
+val meta_spec = thm "meta_spec";
+
+fun projections rule =
+ ProjectRule.projections (ProofContext.init (Thm.theory_of_thm rule)) rule
+ |> map (standard #> RuleCases.save rule);
+
+val supp_prod = thm "supp_prod";
+val fresh_prod = thm "fresh_prod";
+val supports_fresh = thm "supports_fresh";
+val supports_def = thm "Nominal.supports_def";
+val fresh_def = thm "fresh_def";
+val supp_def = thm "supp_def";
+val rev_simps = thms "rev.simps";
+val app_simps = thms "append.simps";
+val at_fin_set_supp = thm "at_fin_set_supp";
+val at_fin_set_fresh = thm "at_fin_set_fresh";
+val abs_fun_eq1 = thm "abs_fun_eq1";
+
+val collect_simp = rewrite_rule [mk_meta_eq mem_Collect_eq];
+
+fun mk_perm Ts t u =
+ let
+ val T = fastype_of1 (Ts, t);
+ val U = fastype_of1 (Ts, u)
+ in Const ("Nominal.perm", T --> U --> U) $ t $ u end;
+
+fun perm_of_pair (x, y) =
+ let
+ val T = fastype_of x;
+ val pT = mk_permT T
+ in Const ("List.list.Cons", HOLogic.mk_prodT (T, T) --> pT --> pT) $
+ HOLogic.mk_prod (x, y) $ Const ("List.list.Nil", pT)
+ end;
+
+fun mk_not_sym ths = maps (fn th => case prop_of th of
+ _ $ (Const ("Not", _) $ (Const ("op =", _) $ _ $ _)) => [th, th RS not_sym]
+ | _ => [th]) ths;
+
+fun fresh_const T U = Const ("Nominal.fresh", T --> U --> HOLogic.boolT);
+fun fresh_star_const T U =
+ Const ("Nominal.fresh_star", HOLogic.mk_setT T --> U --> HOLogic.boolT);
+
+fun gen_add_nominal_datatype prep_typ config new_type_names dts thy =
+ let
+ (* this theory is used just for parsing *)
+
+ val tmp_thy = thy |>
+ Theory.copy |>
+ Sign.add_types (map (fn (tvs, tname, mx, _) =>
+ (Binding.name tname, length tvs, mx)) dts);
+
+ val atoms = atoms_of thy;
+
+ fun prep_constr ((constrs, sorts), (cname, cargs, mx)) =
+ let val (cargs', sorts') = Library.foldl (prep_typ tmp_thy) (([], sorts), cargs)
+ in (constrs @ [(cname, cargs', mx)], sorts') end
+
+ fun prep_dt_spec ((dts, sorts), (tvs, tname, mx, constrs)) =
+ let val (constrs', sorts') = Library.foldl prep_constr (([], sorts), constrs)
+ in (dts @ [(tvs, tname, mx, constrs')], sorts') end
+
+ val (dts', sorts) = Library.foldl prep_dt_spec (([], []), dts);
+ val tyvars = map (map (fn s =>
+ (s, the (AList.lookup (op =) sorts s))) o #1) dts';
+
+ fun inter_sort thy S S' = Type.inter_sort (Sign.tsig_of thy) (S, S');
+ fun augment_sort_typ thy S =
+ let val S = Sign.certify_sort thy S
+ in map_type_tfree (fn (s, S') => TFree (s,
+ if member (op = o apsnd fst) sorts s then inter_sort thy S S' else S'))
+ end;
+ fun augment_sort thy S = map_types (augment_sort_typ thy S);
+
+ val types_syntax = map (fn (tvs, tname, mx, constrs) => (tname, mx)) dts';
+ val constr_syntax = map (fn (tvs, tname, mx, constrs) =>
+ map (fn (cname, cargs, mx) => (cname, mx)) constrs) dts';
+
+ val ps = map (fn (_, n, _, _) =>
+ (Sign.full_bname tmp_thy n, Sign.full_bname tmp_thy (n ^ "_Rep"))) dts;
+ val rps = map Library.swap ps;
+
+ fun replace_types (Type ("Nominal.ABS", [T, U])) =
+ Type ("fun", [T, Type ("Nominal.noption", [replace_types U])])
+ | replace_types (Type (s, Ts)) =
+ Type (getOpt (AList.lookup op = ps s, s), map replace_types Ts)
+ | replace_types T = T;
+
+ val dts'' = map (fn (tvs, tname, mx, constrs) => (tvs, Binding.name (tname ^ "_Rep"), NoSyn,
+ map (fn (cname, cargs, mx) => (Binding.name (cname ^ "_Rep"),
+ map replace_types cargs, NoSyn)) constrs)) dts';
+
+ val new_type_names' = map (fn n => n ^ "_Rep") new_type_names;
+ val full_new_type_names' = map (Sign.full_bname thy) new_type_names';
+
+ val ({induction, ...},thy1) =
+ Datatype.add_datatype config new_type_names' dts'' thy;
+
+ val SOME {descr, ...} = Symtab.lookup
+ (Datatype.get_datatypes thy1) (hd full_new_type_names');
+ fun nth_dtyp i = typ_of_dtyp descr sorts (DtRec i);
+
+ val big_name = space_implode "_" new_type_names;
+
+
+ (**** define permutation functions ****)
+
+ val permT = mk_permT (TFree ("'x", HOLogic.typeS));
+ val pi = Free ("pi", permT);
+ val perm_types = map (fn (i, _) =>
+ let val T = nth_dtyp i
+ in permT --> T --> T end) descr;
+ val perm_names' = DatatypeProp.indexify_names (map (fn (i, _) =>
+ "perm_" ^ name_of_typ (nth_dtyp i)) descr);
+ val perm_names = replicate (length new_type_names) "Nominal.perm" @
+ map (Sign.full_bname thy1) (List.drop (perm_names', length new_type_names));
+ val perm_names_types = perm_names ~~ perm_types;
+ val perm_names_types' = perm_names' ~~ perm_types;
+
+ val perm_eqs = maps (fn (i, (_, _, constrs)) =>
+ let val T = nth_dtyp i
+ in map (fn (cname, dts) =>
+ let
+ val Ts = map (typ_of_dtyp descr sorts) dts;
+ val names = Name.variant_list ["pi"] (DatatypeProp.make_tnames Ts);
+ val args = map Free (names ~~ Ts);
+ val c = Const (cname, Ts ---> T);
+ fun perm_arg (dt, x) =
+ let val T = type_of x
+ in if is_rec_type dt then
+ let val (Us, _) = strip_type T
+ in list_abs (map (pair "x") Us,
+ Free (nth perm_names_types' (body_index dt)) $ pi $
+ list_comb (x, map (fn (i, U) =>
+ Const ("Nominal.perm", permT --> U --> U) $
+ (Const ("List.rev", permT --> permT) $ pi) $
+ Bound i) ((length Us - 1 downto 0) ~~ Us)))
+ end
+ else Const ("Nominal.perm", permT --> T --> T) $ pi $ x
+ end;
+ in
+ (Attrib.empty_binding, HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (Free (nth perm_names_types' i) $
+ Free ("pi", mk_permT (TFree ("'x", HOLogic.typeS))) $
+ list_comb (c, args),
+ list_comb (c, map perm_arg (dts ~~ args)))))
+ end) constrs
+ end) descr;
+
+ val (perm_simps, thy2) =
+ Primrec.add_primrec_overloaded
+ (map (fn (s, sT) => (s, sT, false))
+ (List.take (perm_names' ~~ perm_names_types, length new_type_names)))
+ (map (fn s => (Binding.name s, NONE, NoSyn)) perm_names') perm_eqs thy1;
+
+ (**** prove that permutation functions introduced by unfolding are ****)
+ (**** equivalent to already existing permutation functions ****)
+
+ val _ = warning ("length descr: " ^ string_of_int (length descr));
+ val _ = warning ("length new_type_names: " ^ string_of_int (length new_type_names));
+
+ val perm_indnames = DatatypeProp.make_tnames (map body_type perm_types);
+ val perm_fun_def = PureThy.get_thm thy2 "perm_fun_def";
+
+ val unfolded_perm_eq_thms =
+ if length descr = length new_type_names then []
+ else map standard (List.drop (split_conj_thm
+ (Goal.prove_global thy2 [] []
+ (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
+ (map (fn (c as (s, T), x) =>
+ let val [T1, T2] = binder_types T
+ in HOLogic.mk_eq (Const c $ pi $ Free (x, T2),
+ Const ("Nominal.perm", T) $ pi $ Free (x, T2))
+ end)
+ (perm_names_types ~~ perm_indnames))))
+ (fn _ => EVERY [indtac induction perm_indnames 1,
+ ALLGOALS (asm_full_simp_tac
+ (simpset_of thy2 addsimps [perm_fun_def]))])),
+ length new_type_names));
+
+ (**** prove [] \<bullet> t = t ****)
+
+ val _ = warning "perm_empty_thms";
+
+ val perm_empty_thms = List.concat (map (fn a =>
+ let val permT = mk_permT (Type (a, []))
+ in map standard (List.take (split_conj_thm
+ (Goal.prove_global thy2 [] []
+ (augment_sort thy2 [pt_class_of thy2 a]
+ (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
+ (map (fn ((s, T), x) => HOLogic.mk_eq
+ (Const (s, permT --> T --> T) $
+ Const ("List.list.Nil", permT) $ Free (x, T),
+ Free (x, T)))
+ (perm_names ~~
+ map body_type perm_types ~~ perm_indnames)))))
+ (fn _ => EVERY [indtac induction perm_indnames 1,
+ ALLGOALS (asm_full_simp_tac (simpset_of thy2))])),
+ length new_type_names))
+ end)
+ atoms);
+
+ (**** prove (pi1 @ pi2) \<bullet> t = pi1 \<bullet> (pi2 \<bullet> t) ****)
+
+ val _ = warning "perm_append_thms";
+
+ (*FIXME: these should be looked up statically*)
+ val at_pt_inst = PureThy.get_thm thy2 "at_pt_inst";
+ val pt2 = PureThy.get_thm thy2 "pt2";
+
+ val perm_append_thms = List.concat (map (fn a =>
+ let
+ val permT = mk_permT (Type (a, []));
+ val pi1 = Free ("pi1", permT);
+ val pi2 = Free ("pi2", permT);
+ val pt_inst = pt_inst_of thy2 a;
+ val pt2' = pt_inst RS pt2;
+ val pt2_ax = PureThy.get_thm thy2 (Long_Name.map_base_name (fn s => "pt_" ^ s ^ "2") a);
+ in List.take (map standard (split_conj_thm
+ (Goal.prove_global thy2 [] []
+ (augment_sort thy2 [pt_class_of thy2 a]
+ (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
+ (map (fn ((s, T), x) =>
+ let val perm = Const (s, permT --> T --> T)
+ in HOLogic.mk_eq
+ (perm $ (Const ("List.append", permT --> permT --> permT) $
+ pi1 $ pi2) $ Free (x, T),
+ perm $ pi1 $ (perm $ pi2 $ Free (x, T)))
+ end)
+ (perm_names ~~
+ map body_type perm_types ~~ perm_indnames)))))
+ (fn _ => EVERY [indtac induction perm_indnames 1,
+ ALLGOALS (asm_full_simp_tac (simpset_of thy2 addsimps [pt2', pt2_ax]))]))),
+ length new_type_names)
+ end) atoms);
+
+ (**** prove pi1 ~ pi2 ==> pi1 \<bullet> t = pi2 \<bullet> t ****)
+
+ val _ = warning "perm_eq_thms";
+
+ val pt3 = PureThy.get_thm thy2 "pt3";
+ val pt3_rev = PureThy.get_thm thy2 "pt3_rev";
+
+ val perm_eq_thms = List.concat (map (fn a =>
+ let
+ val permT = mk_permT (Type (a, []));
+ val pi1 = Free ("pi1", permT);
+ val pi2 = Free ("pi2", permT);
+ val at_inst = at_inst_of thy2 a;
+ val pt_inst = pt_inst_of thy2 a;
+ val pt3' = pt_inst RS pt3;
+ val pt3_rev' = at_inst RS (pt_inst RS pt3_rev);
+ val pt3_ax = PureThy.get_thm thy2 (Long_Name.map_base_name (fn s => "pt_" ^ s ^ "3") a);
+ in List.take (map standard (split_conj_thm
+ (Goal.prove_global thy2 [] []
+ (augment_sort thy2 [pt_class_of thy2 a] (Logic.mk_implies
+ (HOLogic.mk_Trueprop (Const ("Nominal.prm_eq",
+ permT --> permT --> HOLogic.boolT) $ pi1 $ pi2),
+ HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
+ (map (fn ((s, T), x) =>
+ let val perm = Const (s, permT --> T --> T)
+ in HOLogic.mk_eq
+ (perm $ pi1 $ Free (x, T),
+ perm $ pi2 $ Free (x, T))
+ end)
+ (perm_names ~~
+ map body_type perm_types ~~ perm_indnames))))))
+ (fn _ => EVERY [indtac induction perm_indnames 1,
+ ALLGOALS (asm_full_simp_tac (simpset_of thy2 addsimps [pt3', pt3_rev', pt3_ax]))]))),
+ length new_type_names)
+ end) atoms);
+
+ (**** prove pi1 \<bullet> (pi2 \<bullet> t) = (pi1 \<bullet> pi2) \<bullet> (pi1 \<bullet> t) ****)
+
+ val cp1 = PureThy.get_thm thy2 "cp1";
+ val dj_cp = PureThy.get_thm thy2 "dj_cp";
+ val pt_perm_compose = PureThy.get_thm thy2 "pt_perm_compose";
+ val pt_perm_compose_rev = PureThy.get_thm thy2 "pt_perm_compose_rev";
+ val dj_perm_perm_forget = PureThy.get_thm thy2 "dj_perm_perm_forget";
+
+ fun composition_instance name1 name2 thy =
+ let
+ val cp_class = cp_class_of thy name1 name2;
+ val pt_class =
+ if name1 = name2 then [pt_class_of thy name1]
+ else [];
+ val permT1 = mk_permT (Type (name1, []));
+ val permT2 = mk_permT (Type (name2, []));
+ val Ts = map body_type perm_types;
+ val cp_inst = cp_inst_of thy name1 name2;
+ val simps = simpset_of thy addsimps (perm_fun_def ::
+ (if name1 <> name2 then
+ let val dj = dj_thm_of thy name2 name1
+ in [dj RS (cp_inst RS dj_cp), dj RS dj_perm_perm_forget] end
+ else
+ let
+ val at_inst = at_inst_of thy name1;
+ val pt_inst = pt_inst_of thy name1;
+ in
+ [cp_inst RS cp1 RS sym,
+ at_inst RS (pt_inst RS pt_perm_compose) RS sym,
+ at_inst RS (pt_inst RS pt_perm_compose_rev) RS sym]
+ end))
+ val sort = Sign.certify_sort thy (cp_class :: pt_class);
+ val thms = split_conj_thm (Goal.prove_global thy [] []
+ (augment_sort thy sort
+ (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
+ (map (fn ((s, T), x) =>
+ let
+ val pi1 = Free ("pi1", permT1);
+ val pi2 = Free ("pi2", permT2);
+ val perm1 = Const (s, permT1 --> T --> T);
+ val perm2 = Const (s, permT2 --> T --> T);
+ val perm3 = Const ("Nominal.perm", permT1 --> permT2 --> permT2)
+ in HOLogic.mk_eq
+ (perm1 $ pi1 $ (perm2 $ pi2 $ Free (x, T)),
+ perm2 $ (perm3 $ pi1 $ pi2) $ (perm1 $ pi1 $ Free (x, T)))
+ end)
+ (perm_names ~~ Ts ~~ perm_indnames)))))
+ (fn _ => EVERY [indtac induction perm_indnames 1,
+ ALLGOALS (asm_full_simp_tac simps)]))
+ in
+ fold (fn (s, tvs) => fn thy => AxClass.prove_arity
+ (s, map (inter_sort thy sort o snd) tvs, [cp_class])
+ (Class.intro_classes_tac [] THEN ALLGOALS (resolve_tac thms)) thy)
+ (full_new_type_names' ~~ tyvars) thy
+ end;
+
+ val (perm_thmss,thy3) = thy2 |>
+ fold (fn name1 => fold (composition_instance name1) atoms) atoms |>
+ fold (fn atom => fn thy =>
+ let val pt_name = pt_class_of thy atom
+ in
+ fold (fn (s, tvs) => fn thy => AxClass.prove_arity
+ (s, map (inter_sort thy [pt_name] o snd) tvs, [pt_name])
+ (EVERY
+ [Class.intro_classes_tac [],
+ resolve_tac perm_empty_thms 1,
+ resolve_tac perm_append_thms 1,
+ resolve_tac perm_eq_thms 1, assume_tac 1]) thy)
+ (full_new_type_names' ~~ tyvars) thy
+ end) atoms |>
+ PureThy.add_thmss
+ [((Binding.name (space_implode "_" new_type_names ^ "_unfolded_perm_eq"),
+ unfolded_perm_eq_thms), [Simplifier.simp_add]),
+ ((Binding.name (space_implode "_" new_type_names ^ "_perm_empty"),
+ perm_empty_thms), [Simplifier.simp_add]),
+ ((Binding.name (space_implode "_" new_type_names ^ "_perm_append"),
+ perm_append_thms), [Simplifier.simp_add]),
+ ((Binding.name (space_implode "_" new_type_names ^ "_perm_eq"),
+ perm_eq_thms), [Simplifier.simp_add])];
+
+ (**** Define representing sets ****)
+
+ val _ = warning "representing sets";
+
+ val rep_set_names = DatatypeProp.indexify_names
+ (map (fn (i, _) => name_of_typ (nth_dtyp i) ^ "_set") descr);
+ val big_rep_name =
+ space_implode "_" (DatatypeProp.indexify_names (List.mapPartial
+ (fn (i, ("Nominal.noption", _, _)) => NONE
+ | (i, _) => SOME (name_of_typ (nth_dtyp i))) descr)) ^ "_set";
+ val _ = warning ("big_rep_name: " ^ big_rep_name);
+
+ fun strip_option (dtf as DtType ("fun", [dt, DtRec i])) =
+ (case AList.lookup op = descr i of
+ SOME ("Nominal.noption", _, [(_, [dt']), _]) =>
+ apfst (cons dt) (strip_option dt')
+ | _ => ([], dtf))
+ | strip_option (DtType ("fun", [dt, DtType ("Nominal.noption", [dt'])])) =
+ apfst (cons dt) (strip_option dt')
+ | strip_option dt = ([], dt);
+
+ val dt_atomTs = distinct op = (map (typ_of_dtyp descr sorts)
+ (List.concat (map (fn (_, (_, _, cs)) => List.concat
+ (map (List.concat o map (fst o strip_option) o snd) cs)) descr)));
+ val dt_atoms = map (fst o dest_Type) dt_atomTs;
+
+ fun make_intr s T (cname, cargs) =
+ let
+ fun mk_prem (dt, (j, j', prems, ts)) =
+ let
+ val (dts, dt') = strip_option dt;
+ val (dts', dt'') = strip_dtyp dt';
+ val Ts = map (typ_of_dtyp descr sorts) dts;
+ val Us = map (typ_of_dtyp descr sorts) dts';
+ val T = typ_of_dtyp descr sorts dt'';
+ val free = mk_Free "x" (Us ---> T) j;
+ val free' = app_bnds free (length Us);
+ fun mk_abs_fun (T, (i, t)) =
+ let val U = fastype_of t
+ in (i + 1, Const ("Nominal.abs_fun", [T, U, T] --->
+ Type ("Nominal.noption", [U])) $ mk_Free "y" T i $ t)
+ end
+ in (j + 1, j' + length Ts,
+ case dt'' of
+ DtRec k => list_all (map (pair "x") Us,
+ HOLogic.mk_Trueprop (Free (List.nth (rep_set_names, k),
+ T --> HOLogic.boolT) $ free')) :: prems
+ | _ => prems,
+ snd (List.foldr mk_abs_fun (j', free) Ts) :: ts)
+ end;
+
+ val (_, _, prems, ts) = List.foldr mk_prem (1, 1, [], []) cargs;
+ val concl = HOLogic.mk_Trueprop (Free (s, T --> HOLogic.boolT) $
+ list_comb (Const (cname, map fastype_of ts ---> T), ts))
+ in Logic.list_implies (prems, concl)
+ end;
+
+ val (intr_ts, (rep_set_names', recTs')) =
+ apfst List.concat (apsnd ListPair.unzip (ListPair.unzip (List.mapPartial
+ (fn ((_, ("Nominal.noption", _, _)), _) => NONE
+ | ((i, (_, _, constrs)), rep_set_name) =>
+ let val T = nth_dtyp i
+ in SOME (map (make_intr rep_set_name T) constrs,
+ (rep_set_name, T))
+ end)
+ (descr ~~ rep_set_names))));
+ val rep_set_names'' = map (Sign.full_bname thy3) rep_set_names';
+
+ val ({raw_induct = rep_induct, intrs = rep_intrs, ...}, thy4) =
+ Inductive.add_inductive_global (serial_string ())
+ {quiet_mode = false, verbose = false, kind = Thm.internalK,
+ alt_name = Binding.name big_rep_name, coind = false, no_elim = true, no_ind = false,
+ skip_mono = true, fork_mono = false}
+ (map (fn (s, T) => ((Binding.name s, T --> HOLogic.boolT), NoSyn))
+ (rep_set_names' ~~ recTs'))
+ [] (map (fn x => (Attrib.empty_binding, x)) intr_ts) [] thy3;
+
+ (**** Prove that representing set is closed under permutation ****)
+
+ val _ = warning "proving closure under permutation...";
+
+ val abs_perm = PureThy.get_thms thy4 "abs_perm";
+
+ val perm_indnames' = List.mapPartial
+ (fn (x, (_, ("Nominal.noption", _, _))) => NONE | (x, _) => SOME x)
+ (perm_indnames ~~ descr);
+
+ fun mk_perm_closed name = map (fn th => standard (th RS mp))
+ (List.take (split_conj_thm (Goal.prove_global thy4 [] []
+ (augment_sort thy4
+ (pt_class_of thy4 name :: map (cp_class_of thy4 name) (dt_atoms \ name))
+ (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj (map
+ (fn ((s, T), x) =>
+ let
+ val S = Const (s, T --> HOLogic.boolT);
+ val permT = mk_permT (Type (name, []))
+ in HOLogic.mk_imp (S $ Free (x, T),
+ S $ (Const ("Nominal.perm", permT --> T --> T) $
+ Free ("pi", permT) $ Free (x, T)))
+ end) (rep_set_names'' ~~ recTs' ~~ perm_indnames')))))
+ (fn _ => EVERY
+ [indtac rep_induct [] 1,
+ ALLGOALS (simp_tac (simpset_of thy4 addsimps
+ (symmetric perm_fun_def :: abs_perm))),
+ ALLGOALS (resolve_tac rep_intrs THEN_ALL_NEW assume_tac)])),
+ length new_type_names));
+
+ val perm_closed_thmss = map mk_perm_closed atoms;
+
+ (**** typedef ****)
+
+ val _ = warning "defining type...";
+
+ val (typedefs, thy6) =
+ thy4
+ |> fold_map (fn ((((name, mx), tvs), (cname, U)), name') => fn thy =>
+ Typedef.add_typedef false (SOME (Binding.name name'))
+ (Binding.name name, map fst tvs, mx)
+ (Const ("Collect", (U --> HOLogic.boolT) --> HOLogic.mk_setT U) $
+ Const (cname, U --> HOLogic.boolT)) NONE
+ (rtac exI 1 THEN rtac CollectI 1 THEN
+ QUIET_BREADTH_FIRST (has_fewer_prems 1)
+ (resolve_tac rep_intrs 1)) thy |> (fn ((_, r), thy) =>
+ let
+ val permT = mk_permT
+ (TFree (Name.variant (map fst tvs) "'a", HOLogic.typeS));
+ val pi = Free ("pi", permT);
+ val T = Type (Sign.intern_type thy name, map TFree tvs);
+ in apfst (pair r o hd)
+ (PureThy.add_defs_unchecked true [((Binding.name ("prm_" ^ name ^ "_def"), Logic.mk_equals
+ (Const ("Nominal.perm", permT --> T --> T) $ pi $ Free ("x", T),
+ Const (Sign.intern_const thy ("Abs_" ^ name), U --> T) $
+ (Const ("Nominal.perm", permT --> U --> U) $ pi $
+ (Const (Sign.intern_const thy ("Rep_" ^ name), T --> U) $
+ Free ("x", T))))), [])] thy)
+ end))
+ (types_syntax ~~ tyvars ~~
+ List.take (rep_set_names'' ~~ recTs', length new_type_names) ~~
+ new_type_names);
+
+ val perm_defs = map snd typedefs;
+ val Abs_inverse_thms = map (collect_simp o #Abs_inverse o fst) typedefs;
+ val Rep_inverse_thms = map (#Rep_inverse o fst) typedefs;
+ val Rep_thms = map (collect_simp o #Rep o fst) typedefs;
+
+
+ (** prove that new types are in class pt_<name> **)
+
+ val _ = warning "prove that new types are in class pt_<name> ...";
+
+ fun pt_instance (atom, perm_closed_thms) =
+ fold (fn ((((((Abs_inverse, Rep_inverse), Rep),
+ perm_def), name), tvs), perm_closed) => fn thy =>
+ let
+ val pt_class = pt_class_of thy atom;
+ val sort = Sign.certify_sort thy
+ (pt_class :: map (cp_class_of thy atom) (dt_atoms \ atom))
+ in AxClass.prove_arity
+ (Sign.intern_type thy name,
+ map (inter_sort thy sort o snd) tvs, [pt_class])
+ (EVERY [Class.intro_classes_tac [],
+ rewrite_goals_tac [perm_def],
+ asm_full_simp_tac (simpset_of thy addsimps [Rep_inverse]) 1,
+ asm_full_simp_tac (simpset_of thy addsimps
+ [Rep RS perm_closed RS Abs_inverse]) 1,
+ asm_full_simp_tac (HOL_basic_ss addsimps [PureThy.get_thm thy
+ ("pt_" ^ Long_Name.base_name atom ^ "3")]) 1]) thy
+ end)
+ (Abs_inverse_thms ~~ Rep_inverse_thms ~~ Rep_thms ~~ perm_defs ~~
+ new_type_names ~~ tyvars ~~ perm_closed_thms);
+
+
+ (** prove that new types are in class cp_<name1>_<name2> **)
+
+ val _ = warning "prove that new types are in class cp_<name1>_<name2> ...";
+
+ fun cp_instance (atom1, perm_closed_thms1) (atom2, perm_closed_thms2) thy =
+ let
+ val cp_class = cp_class_of thy atom1 atom2;
+ val sort = Sign.certify_sort thy
+ (pt_class_of thy atom1 :: map (cp_class_of thy atom1) (dt_atoms \ atom1) @
+ (if atom1 = atom2 then [cp_class_of thy atom1 atom1] else
+ pt_class_of thy atom2 :: map (cp_class_of thy atom2) (dt_atoms \ atom2)));
+ val cp1' = cp_inst_of thy atom1 atom2 RS cp1
+ in fold (fn ((((((Abs_inverse, Rep),
+ perm_def), name), tvs), perm_closed1), perm_closed2) => fn thy =>
+ AxClass.prove_arity
+ (Sign.intern_type thy name,
+ map (inter_sort thy sort o snd) tvs, [cp_class])
+ (EVERY [Class.intro_classes_tac [],
+ rewrite_goals_tac [perm_def],
+ asm_full_simp_tac (simpset_of thy addsimps
+ ((Rep RS perm_closed1 RS Abs_inverse) ::
+ (if atom1 = atom2 then []
+ else [Rep RS perm_closed2 RS Abs_inverse]))) 1,
+ cong_tac 1,
+ rtac refl 1,
+ rtac cp1' 1]) thy)
+ (Abs_inverse_thms ~~ Rep_thms ~~ perm_defs ~~ new_type_names ~~
+ tyvars ~~ perm_closed_thms1 ~~ perm_closed_thms2) thy
+ end;
+
+ val thy7 = fold (fn x => fn thy => thy |>
+ pt_instance x |>
+ fold (cp_instance x) (atoms ~~ perm_closed_thmss))
+ (atoms ~~ perm_closed_thmss) thy6;
+
+ (**** constructors ****)
+
+ fun mk_abs_fun (x, t) =
+ let
+ val T = fastype_of x;
+ val U = fastype_of t
+ in
+ Const ("Nominal.abs_fun", T --> U --> T -->
+ Type ("Nominal.noption", [U])) $ x $ t
+ end;
+
+ val (ty_idxs, _) = List.foldl
+ (fn ((i, ("Nominal.noption", _, _)), p) => p
+ | ((i, _), (ty_idxs, j)) => (ty_idxs @ [(i, j)], j + 1)) ([], 0) descr;
+
+ fun reindex (DtType (s, dts)) = DtType (s, map reindex dts)
+ | reindex (DtRec i) = DtRec (the (AList.lookup op = ty_idxs i))
+ | reindex dt = dt;
+
+ fun strip_suffix i s = implode (List.take (explode s, size s - i));
+
+ (** strips the "_Rep" in type names *)
+ fun strip_nth_name i s =
+ let val xs = Long_Name.explode s;
+ in Long_Name.implode (Library.nth_map (length xs - i) (strip_suffix 4) xs) end;
+
+ val (descr'', ndescr) = ListPair.unzip (map_filter
+ (fn (i, ("Nominal.noption", _, _)) => NONE
+ | (i, (s, dts, constrs)) =>
+ let
+ val SOME index = AList.lookup op = ty_idxs i;
+ val (constrs2, constrs1) =
+ map_split (fn (cname, cargs) =>
+ apsnd (pair (strip_nth_name 2 (strip_nth_name 1 cname)))
+ (fold_map (fn dt => fn dts =>
+ let val (dts', dt') = strip_option dt
+ in ((length dts, length dts'), dts @ dts' @ [reindex dt']) end)
+ cargs [])) constrs
+ in SOME ((index, (strip_nth_name 1 s, map reindex dts, constrs1)),
+ (index, constrs2))
+ end) descr);
+
+ val (descr1, descr2) = chop (length new_type_names) descr'';
+ val descr' = [descr1, descr2];
+
+ fun partition_cargs idxs xs = map (fn (i, j) =>
+ (List.take (List.drop (xs, i), j), List.nth (xs, i + j))) idxs;
+
+ val pdescr = map (fn ((i, (s, dts, constrs)), (_, idxss)) => (i, (s, dts,
+ map (fn ((cname, cargs), idxs) => (cname, partition_cargs idxs cargs))
+ (constrs ~~ idxss)))) (descr'' ~~ ndescr);
+
+ fun nth_dtyp' i = typ_of_dtyp descr'' sorts (DtRec i);
+
+ val rep_names = map (fn s =>
+ Sign.intern_const thy7 ("Rep_" ^ s)) new_type_names;
+ val abs_names = map (fn s =>
+ Sign.intern_const thy7 ("Abs_" ^ s)) new_type_names;
+
+ val recTs = get_rec_types descr'' sorts;
+ val newTs' = Library.take (length new_type_names, recTs');
+ val newTs = Library.take (length new_type_names, recTs);
+
+ val full_new_type_names = map (Sign.full_bname thy) new_type_names;
+
+ fun make_constr_def tname T T' ((thy, defs, eqns),
+ (((cname_rep, _), (cname, cargs)), (cname', mx))) =
+ let
+ fun constr_arg ((dts, dt), (j, l_args, r_args)) =
+ let
+ val xs = map (fn (dt, i) => mk_Free "x" (typ_of_dtyp descr'' sorts dt) i)
+ (dts ~~ (j upto j + length dts - 1))
+ val x = mk_Free "x" (typ_of_dtyp descr'' sorts dt) (j + length dts)
+ in
+ (j + length dts + 1,
+ xs @ x :: l_args,
+ List.foldr mk_abs_fun
+ (case dt of
+ DtRec k => if k < length new_type_names then
+ Const (List.nth (rep_names, k), typ_of_dtyp descr'' sorts dt -->
+ typ_of_dtyp descr sorts dt) $ x
+ else error "nested recursion not (yet) supported"
+ | _ => x) xs :: r_args)
+ end
+
+ val (_, l_args, r_args) = List.foldr constr_arg (1, [], []) cargs;
+ val abs_name = Sign.intern_const thy ("Abs_" ^ tname);
+ val rep_name = Sign.intern_const thy ("Rep_" ^ tname);
+ val constrT = map fastype_of l_args ---> T;
+ val lhs = list_comb (Const (cname, constrT), l_args);
+ val rhs = list_comb (Const (cname_rep, map fastype_of r_args ---> T'), r_args);
+ val def = Logic.mk_equals (lhs, Const (abs_name, T' --> T) $ rhs);
+ val eqn = HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (Const (rep_name, T --> T') $ lhs, rhs));
+ val def_name = (Long_Name.base_name cname) ^ "_def";
+ val ([def_thm], thy') = thy |>
+ Sign.add_consts_i [(Binding.name cname', constrT, mx)] |>
+ (PureThy.add_defs false o map Thm.no_attributes) [(Binding.name def_name, def)]
+ in (thy', defs @ [def_thm], eqns @ [eqn]) end;
+
+ fun dt_constr_defs ((thy, defs, eqns, dist_lemmas), ((((((_, (_, _, constrs)),
+ (_, (_, _, constrs'))), tname), T), T'), constr_syntax)) =
+ let
+ val rep_const = cterm_of thy
+ (Const (Sign.intern_const thy ("Rep_" ^ tname), T --> T'));
+ val dist = standard (cterm_instantiate [(cterm_of thy distinct_f, rep_const)] distinct_lemma);
+ val (thy', defs', eqns') = Library.foldl (make_constr_def tname T T')
+ ((Sign.add_path tname thy, defs, []), constrs ~~ constrs' ~~ constr_syntax)
+ in
+ (parent_path (#flat_names config) thy', defs', eqns @ [eqns'], dist_lemmas @ [dist])
+ end;
+
+ val (thy8, constr_defs, constr_rep_eqns, dist_lemmas) = Library.foldl dt_constr_defs
+ ((thy7, [], [], []), List.take (descr, length new_type_names) ~~
+ List.take (pdescr, length new_type_names) ~~
+ new_type_names ~~ newTs ~~ newTs' ~~ constr_syntax);
+
+ val abs_inject_thms = map (collect_simp o #Abs_inject o fst) typedefs
+ val rep_inject_thms = map (#Rep_inject o fst) typedefs
+
+ (* prove theorem Rep_i (Constr_j ...) = Constr'_j ... *)
+
+ fun prove_constr_rep_thm eqn =
+ let
+ val inj_thms = map (fn r => r RS iffD1) abs_inject_thms;
+ val rewrites = constr_defs @ map mk_meta_eq Rep_inverse_thms
+ in Goal.prove_global thy8 [] [] eqn (fn _ => EVERY
+ [resolve_tac inj_thms 1,
+ rewrite_goals_tac rewrites,
+ rtac refl 3,
+ resolve_tac rep_intrs 2,
+ REPEAT (resolve_tac Rep_thms 1)])
+ end;
+
+ val constr_rep_thmss = map (map prove_constr_rep_thm) constr_rep_eqns;
+
+ (* prove theorem pi \<bullet> Rep_i x = Rep_i (pi \<bullet> x) *)
+
+ fun prove_perm_rep_perm (atom, perm_closed_thms) = map (fn th =>
+ let
+ val _ $ (_ $ (Rep $ x)) = Logic.unvarify (prop_of th);
+ val Type ("fun", [T, U]) = fastype_of Rep;
+ val permT = mk_permT (Type (atom, []));
+ val pi = Free ("pi", permT);
+ in
+ Goal.prove_global thy8 [] []
+ (augment_sort thy8
+ (pt_class_of thy8 atom :: map (cp_class_of thy8 atom) (dt_atoms \ atom))
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (Const ("Nominal.perm", permT --> U --> U) $ pi $ (Rep $ x),
+ Rep $ (Const ("Nominal.perm", permT --> T --> T) $ pi $ x)))))
+ (fn _ => simp_tac (HOL_basic_ss addsimps (perm_defs @ Abs_inverse_thms @
+ perm_closed_thms @ Rep_thms)) 1)
+ end) Rep_thms;
+
+ val perm_rep_perm_thms = List.concat (map prove_perm_rep_perm
+ (atoms ~~ perm_closed_thmss));
+
+ (* prove distinctness theorems *)
+
+ val distinct_props = DatatypeProp.make_distincts descr' sorts;
+ val dist_rewrites = map2 (fn rep_thms => fn dist_lemma =>
+ dist_lemma :: rep_thms @ [In0_eq, In1_eq, In0_not_In1, In1_not_In0])
+ constr_rep_thmss dist_lemmas;
+
+ fun prove_distinct_thms _ (_, []) = []
+ | prove_distinct_thms (p as (rep_thms, dist_lemma)) (k, t :: ts) =
+ let
+ val dist_thm = Goal.prove_global thy8 [] [] t (fn _ =>
+ simp_tac (simpset_of thy8 addsimps (dist_lemma :: rep_thms)) 1)
+ in dist_thm :: standard (dist_thm RS not_sym) ::
+ prove_distinct_thms p (k, ts)
+ end;
+
+ val distinct_thms = map2 prove_distinct_thms
+ (constr_rep_thmss ~~ dist_lemmas) distinct_props;
+
+ (** prove equations for permutation functions **)
+
+ val perm_simps' = map (fn (((i, (_, _, constrs)), tname), constr_rep_thms) =>
+ let val T = nth_dtyp' i
+ in List.concat (map (fn (atom, perm_closed_thms) =>
+ map (fn ((cname, dts), constr_rep_thm) =>
+ let
+ val cname = Sign.intern_const thy8
+ (Long_Name.append tname (Long_Name.base_name cname));
+ val permT = mk_permT (Type (atom, []));
+ val pi = Free ("pi", permT);
+
+ fun perm t =
+ let val T = fastype_of t
+ in Const ("Nominal.perm", permT --> T --> T) $ pi $ t end;
+
+ fun constr_arg ((dts, dt), (j, l_args, r_args)) =
+ let
+ val Ts = map (typ_of_dtyp descr'' sorts) dts;
+ val xs = map (fn (T, i) => mk_Free "x" T i)
+ (Ts ~~ (j upto j + length dts - 1))
+ val x = mk_Free "x" (typ_of_dtyp descr'' sorts dt) (j + length dts)
+ in
+ (j + length dts + 1,
+ xs @ x :: l_args,
+ map perm (xs @ [x]) @ r_args)
+ end
+
+ val (_, l_args, r_args) = List.foldr constr_arg (1, [], []) dts;
+ val c = Const (cname, map fastype_of l_args ---> T)
+ in
+ Goal.prove_global thy8 [] []
+ (augment_sort thy8
+ (pt_class_of thy8 atom :: map (cp_class_of thy8 atom) (dt_atoms \ atom))
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (perm (list_comb (c, l_args)), list_comb (c, r_args)))))
+ (fn _ => EVERY
+ [simp_tac (simpset_of thy8 addsimps (constr_rep_thm :: perm_defs)) 1,
+ simp_tac (HOL_basic_ss addsimps (Rep_thms @ Abs_inverse_thms @
+ constr_defs @ perm_closed_thms)) 1,
+ TRY (simp_tac (HOL_basic_ss addsimps
+ (symmetric perm_fun_def :: abs_perm)) 1),
+ TRY (simp_tac (HOL_basic_ss addsimps
+ (perm_fun_def :: perm_defs @ Rep_thms @ Abs_inverse_thms @
+ perm_closed_thms)) 1)])
+ end) (constrs ~~ constr_rep_thms)) (atoms ~~ perm_closed_thmss))
+ end) (List.take (pdescr, length new_type_names) ~~ new_type_names ~~ constr_rep_thmss);
+
+ (** prove injectivity of constructors **)
+
+ val rep_inject_thms' = map (fn th => th RS sym) rep_inject_thms;
+ val alpha = PureThy.get_thms thy8 "alpha";
+ val abs_fresh = PureThy.get_thms thy8 "abs_fresh";
+
+ val pt_cp_sort =
+ map (pt_class_of thy8) dt_atoms @
+ maps (fn s => map (cp_class_of thy8 s) (dt_atoms \ s)) dt_atoms;
+
+ val inject_thms = map (fn (((i, (_, _, constrs)), tname), constr_rep_thms) =>
+ let val T = nth_dtyp' i
+ in List.mapPartial (fn ((cname, dts), constr_rep_thm) =>
+ if null dts then NONE else SOME
+ let
+ val cname = Sign.intern_const thy8
+ (Long_Name.append tname (Long_Name.base_name cname));
+
+ fun make_inj ((dts, dt), (j, args1, args2, eqs)) =
+ let
+ val Ts_idx = map (typ_of_dtyp descr'' sorts) dts ~~ (j upto j + length dts - 1);
+ val xs = map (fn (T, i) => mk_Free "x" T i) Ts_idx;
+ val ys = map (fn (T, i) => mk_Free "y" T i) Ts_idx;
+ val x = mk_Free "x" (typ_of_dtyp descr'' sorts dt) (j + length dts);
+ val y = mk_Free "y" (typ_of_dtyp descr'' sorts dt) (j + length dts)
+ in
+ (j + length dts + 1,
+ xs @ (x :: args1), ys @ (y :: args2),
+ HOLogic.mk_eq
+ (List.foldr mk_abs_fun x xs, List.foldr mk_abs_fun y ys) :: eqs)
+ end;
+
+ val (_, args1, args2, eqs) = List.foldr make_inj (1, [], [], []) dts;
+ val Ts = map fastype_of args1;
+ val c = Const (cname, Ts ---> T)
+ in
+ Goal.prove_global thy8 [] []
+ (augment_sort thy8 pt_cp_sort
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (HOLogic.mk_eq (list_comb (c, args1), list_comb (c, args2)),
+ foldr1 HOLogic.mk_conj eqs))))
+ (fn _ => EVERY
+ [asm_full_simp_tac (simpset_of thy8 addsimps (constr_rep_thm ::
+ rep_inject_thms')) 1,
+ TRY (asm_full_simp_tac (HOL_basic_ss addsimps (fresh_def :: supp_def ::
+ alpha @ abs_perm @ abs_fresh @ rep_inject_thms @
+ perm_rep_perm_thms)) 1)])
+ end) (constrs ~~ constr_rep_thms)
+ end) (List.take (pdescr, length new_type_names) ~~ new_type_names ~~ constr_rep_thmss);
+
+ (** equations for support and freshness **)
+
+ val (supp_thms, fresh_thms) = ListPair.unzip (map ListPair.unzip
+ (map (fn ((((i, (_, _, constrs)), tname), inject_thms'), perm_thms') =>
+ let val T = nth_dtyp' i
+ in List.concat (map (fn (cname, dts) => map (fn atom =>
+ let
+ val cname = Sign.intern_const thy8
+ (Long_Name.append tname (Long_Name.base_name cname));
+ val atomT = Type (atom, []);
+
+ fun process_constr ((dts, dt), (j, args1, args2)) =
+ let
+ val Ts_idx = map (typ_of_dtyp descr'' sorts) dts ~~ (j upto j + length dts - 1);
+ val xs = map (fn (T, i) => mk_Free "x" T i) Ts_idx;
+ val x = mk_Free "x" (typ_of_dtyp descr'' sorts dt) (j + length dts)
+ in
+ (j + length dts + 1,
+ xs @ (x :: args1), List.foldr mk_abs_fun x xs :: args2)
+ end;
+
+ val (_, args1, args2) = List.foldr process_constr (1, [], []) dts;
+ val Ts = map fastype_of args1;
+ val c = list_comb (Const (cname, Ts ---> T), args1);
+ fun supp t =
+ Const ("Nominal.supp", fastype_of t --> HOLogic.mk_setT atomT) $ t;
+ fun fresh t = fresh_const atomT (fastype_of t) $ Free ("a", atomT) $ t;
+ val supp_thm = Goal.prove_global thy8 [] []
+ (augment_sort thy8 pt_cp_sort
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (supp c,
+ if null dts then HOLogic.mk_set atomT []
+ else foldr1 (HOLogic.mk_binop @{const_name Un}) (map supp args2)))))
+ (fn _ =>
+ simp_tac (HOL_basic_ss addsimps (supp_def ::
+ Un_assoc :: de_Morgan_conj :: Collect_disj_eq :: finite_Un ::
+ symmetric empty_def :: finite_emptyI :: simp_thms @
+ abs_perm @ abs_fresh @ inject_thms' @ perm_thms')) 1)
+ in
+ (supp_thm,
+ Goal.prove_global thy8 [] [] (augment_sort thy8 pt_cp_sort
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (fresh c,
+ if null dts then HOLogic.true_const
+ else foldr1 HOLogic.mk_conj (map fresh args2)))))
+ (fn _ =>
+ simp_tac (HOL_ss addsimps [Un_iff, empty_iff, fresh_def, supp_thm]) 1))
+ end) atoms) constrs)
+ end) (List.take (pdescr, length new_type_names) ~~ new_type_names ~~ inject_thms ~~ perm_simps')));
+
+ (**** weak induction theorem ****)
+
+ fun mk_indrule_lemma ((prems, concls), (((i, _), T), U)) =
+ let
+ val Rep_t = Const (List.nth (rep_names, i), T --> U) $
+ mk_Free "x" T i;
+
+ val Abs_t = Const (List.nth (abs_names, i), U --> T)
+
+ in (prems @ [HOLogic.imp $
+ (Const (List.nth (rep_set_names'', i), U --> HOLogic.boolT) $ Rep_t) $
+ (mk_Free "P" (T --> HOLogic.boolT) (i + 1) $ (Abs_t $ Rep_t))],
+ concls @ [mk_Free "P" (T --> HOLogic.boolT) (i + 1) $ mk_Free "x" T i])
+ end;
+
+ val (indrule_lemma_prems, indrule_lemma_concls) =
+ Library.foldl mk_indrule_lemma (([], []), (descr'' ~~ recTs ~~ recTs'));
+
+ val indrule_lemma = Goal.prove_global thy8 [] []
+ (Logic.mk_implies
+ (HOLogic.mk_Trueprop (mk_conj indrule_lemma_prems),
+ HOLogic.mk_Trueprop (mk_conj indrule_lemma_concls))) (fn _ => EVERY
+ [REPEAT (etac conjE 1),
+ REPEAT (EVERY
+ [TRY (rtac conjI 1), full_simp_tac (HOL_basic_ss addsimps Rep_inverse_thms) 1,
+ etac mp 1, resolve_tac Rep_thms 1])]);
+
+ val Ps = map head_of (HOLogic.dest_conj (HOLogic.dest_Trueprop (concl_of indrule_lemma)));
+ val frees = if length Ps = 1 then [Free ("P", snd (dest_Var (hd Ps)))] else
+ map (Free o apfst fst o dest_Var) Ps;
+ val indrule_lemma' = cterm_instantiate
+ (map (cterm_of thy8) Ps ~~ map (cterm_of thy8) frees) indrule_lemma;
+
+ val Abs_inverse_thms' = map (fn r => r RS subst) Abs_inverse_thms;
+
+ val dt_induct_prop = DatatypeProp.make_ind descr' sorts;
+ val dt_induct = Goal.prove_global thy8 []
+ (Logic.strip_imp_prems dt_induct_prop) (Logic.strip_imp_concl dt_induct_prop)
+ (fn {prems, ...} => EVERY
+ [rtac indrule_lemma' 1,
+ (indtac rep_induct [] THEN_ALL_NEW ObjectLogic.atomize_prems_tac) 1,
+ EVERY (map (fn (prem, r) => (EVERY
+ [REPEAT (eresolve_tac Abs_inverse_thms' 1),
+ simp_tac (HOL_basic_ss addsimps [symmetric r]) 1,
+ DEPTH_SOLVE_1 (ares_tac [prem] 1 ORELSE etac allE 1)]))
+ (prems ~~ constr_defs))]);
+
+ val case_names_induct = mk_case_names_induct descr'';
+
+ (**** prove that new datatypes have finite support ****)
+
+ val _ = warning "proving finite support for the new datatype";
+
+ val indnames = DatatypeProp.make_tnames recTs;
+
+ val abs_supp = PureThy.get_thms thy8 "abs_supp";
+ val supp_atm = PureThy.get_thms thy8 "supp_atm";
+
+ val finite_supp_thms = map (fn atom =>
+ let val atomT = Type (atom, [])
+ in map standard (List.take
+ (split_conj_thm (Goal.prove_global thy8 [] []
+ (augment_sort thy8 (fs_class_of thy8 atom :: pt_cp_sort)
+ (HOLogic.mk_Trueprop
+ (foldr1 HOLogic.mk_conj (map (fn (s, T) =>
+ Const ("Finite_Set.finite", HOLogic.mk_setT atomT --> HOLogic.boolT) $
+ (Const ("Nominal.supp", T --> HOLogic.mk_setT atomT) $ Free (s, T)))
+ (indnames ~~ recTs)))))
+ (fn _ => indtac dt_induct indnames 1 THEN
+ ALLGOALS (asm_full_simp_tac (simpset_of thy8 addsimps
+ (abs_supp @ supp_atm @
+ PureThy.get_thms thy8 ("fs_" ^ Long_Name.base_name atom ^ "1") @
+ List.concat supp_thms))))),
+ length new_type_names))
+ end) atoms;
+
+ val simp_atts = replicate (length new_type_names) [Simplifier.simp_add];
+
+ (* Function to add both the simp and eqvt attributes *)
+ (* These two attributes are duplicated on all the types in the mutual nominal datatypes *)
+
+ val simp_eqvt_atts = replicate (length new_type_names) [Simplifier.simp_add, NominalThmDecls.eqvt_add];
+
+ val (_, thy9) = thy8 |>
+ Sign.add_path big_name |>
+ PureThy.add_thms [((Binding.name "induct", dt_induct), [case_names_induct])] ||>>
+ PureThy.add_thmss [((Binding.name "inducts", projections dt_induct), [case_names_induct])] ||>
+ Sign.parent_path ||>>
+ DatatypeAux.store_thmss_atts "distinct" new_type_names simp_atts distinct_thms ||>>
+ DatatypeAux.store_thmss "constr_rep" new_type_names constr_rep_thmss ||>>
+ DatatypeAux.store_thmss_atts "perm" new_type_names simp_eqvt_atts perm_simps' ||>>
+ DatatypeAux.store_thmss "inject" new_type_names inject_thms ||>>
+ DatatypeAux.store_thmss "supp" new_type_names supp_thms ||>>
+ DatatypeAux.store_thmss_atts "fresh" new_type_names simp_atts fresh_thms ||>
+ fold (fn (atom, ths) => fn thy =>
+ let
+ val class = fs_class_of thy atom;
+ val sort = Sign.certify_sort thy (class :: pt_cp_sort)
+ in fold (fn Type (s, Ts) => AxClass.prove_arity
+ (s, map (inter_sort thy sort o snd o dest_TFree) Ts, [class])
+ (Class.intro_classes_tac [] THEN resolve_tac ths 1)) newTs thy
+ end) (atoms ~~ finite_supp_thms);
+
+ (**** strong induction theorem ****)
+
+ val pnames = if length descr'' = 1 then ["P"]
+ else map (fn i => "P" ^ string_of_int i) (1 upto length descr'');
+ val ind_sort = if null dt_atomTs then HOLogic.typeS
+ else Sign.certify_sort thy9 (map (fs_class_of thy9) dt_atoms);
+ val fsT = TFree ("'n", ind_sort);
+ val fsT' = TFree ("'n", HOLogic.typeS);
+
+ val fresh_fs = map (fn (s, T) => (T, Free (s, fsT' --> HOLogic.mk_setT T)))
+ (DatatypeProp.indexify_names (replicate (length dt_atomTs) "f") ~~ dt_atomTs);
+
+ fun make_pred fsT i T =
+ Free (List.nth (pnames, i), fsT --> T --> HOLogic.boolT);
+
+ fun mk_fresh1 xs [] = []
+ | mk_fresh1 xs ((y as (_, T)) :: ys) = map (fn x => HOLogic.mk_Trueprop
+ (HOLogic.mk_not (HOLogic.mk_eq (Free y, Free x))))
+ (filter (fn (_, U) => T = U) (rev xs)) @
+ mk_fresh1 (y :: xs) ys;
+
+ fun mk_fresh2 xss [] = []
+ | mk_fresh2 xss ((p as (ys, _)) :: yss) = List.concat (map (fn y as (_, T) =>
+ map (fn (_, x as (_, U)) => HOLogic.mk_Trueprop
+ (fresh_const T U $ Free y $ Free x)) (rev xss @ yss)) ys) @
+ mk_fresh2 (p :: xss) yss;
+
+ fun make_ind_prem fsT f k T ((cname, cargs), idxs) =
+ let
+ val recs = List.filter is_rec_type cargs;
+ val Ts = map (typ_of_dtyp descr'' sorts) cargs;
+ val recTs' = map (typ_of_dtyp descr'' sorts) recs;
+ val tnames = Name.variant_list pnames (DatatypeProp.make_tnames Ts);
+ val rec_tnames = map fst (List.filter (is_rec_type o snd) (tnames ~~ cargs));
+ val frees = tnames ~~ Ts;
+ val frees' = partition_cargs idxs frees;
+ val z = (Name.variant tnames "z", fsT);
+
+ fun mk_prem ((dt, s), T) =
+ let
+ val (Us, U) = strip_type T;
+ val l = length Us
+ in list_all (z :: map (pair "x") Us, HOLogic.mk_Trueprop
+ (make_pred fsT (body_index dt) U $ Bound l $ app_bnds (Free (s, T)) l))
+ end;
+
+ val prems = map mk_prem (recs ~~ rec_tnames ~~ recTs');
+ val prems' = map (fn p as (_, T) => HOLogic.mk_Trueprop
+ (f T (Free p) (Free z))) (List.concat (map fst frees')) @
+ mk_fresh1 [] (List.concat (map fst frees')) @
+ mk_fresh2 [] frees'
+
+ in list_all_free (frees @ [z], Logic.list_implies (prems' @ prems,
+ HOLogic.mk_Trueprop (make_pred fsT k T $ Free z $
+ list_comb (Const (cname, Ts ---> T), map Free frees))))
+ end;
+
+ val ind_prems = List.concat (map (fn (((i, (_, _, constrs)), (_, idxss)), T) =>
+ map (make_ind_prem fsT (fn T => fn t => fn u =>
+ fresh_const T fsT $ t $ u) i T)
+ (constrs ~~ idxss)) (descr'' ~~ ndescr ~~ recTs));
+ val tnames = DatatypeProp.make_tnames recTs;
+ val zs = Name.variant_list tnames (replicate (length descr'') "z");
+ val ind_concl = HOLogic.mk_Trueprop (foldr1 (HOLogic.mk_binop "op &")
+ (map (fn ((((i, _), T), tname), z) =>
+ make_pred fsT i T $ Free (z, fsT) $ Free (tname, T))
+ (descr'' ~~ recTs ~~ tnames ~~ zs)));
+ val induct = Logic.list_implies (ind_prems, ind_concl);
+
+ val ind_prems' =
+ map (fn (_, f as Free (_, T)) => list_all_free ([("x", fsT')],
+ HOLogic.mk_Trueprop (Const ("Finite_Set.finite",
+ (snd (split_last (binder_types T)) --> HOLogic.boolT) -->
+ HOLogic.boolT) $ (f $ Free ("x", fsT'))))) fresh_fs @
+ List.concat (map (fn (((i, (_, _, constrs)), (_, idxss)), T) =>
+ map (make_ind_prem fsT' (fn T => fn t => fn u => HOLogic.Not $
+ HOLogic.mk_mem (t, the (AList.lookup op = fresh_fs T) $ u)) i T)
+ (constrs ~~ idxss)) (descr'' ~~ ndescr ~~ recTs));
+ val ind_concl' = HOLogic.mk_Trueprop (foldr1 (HOLogic.mk_binop "op &")
+ (map (fn ((((i, _), T), tname), z) =>
+ make_pred fsT' i T $ Free (z, fsT') $ Free (tname, T))
+ (descr'' ~~ recTs ~~ tnames ~~ zs)));
+ val induct' = Logic.list_implies (ind_prems', ind_concl');
+
+ val aux_ind_vars =
+ (DatatypeProp.indexify_names (replicate (length dt_atomTs) "pi") ~~
+ map mk_permT dt_atomTs) @ [("z", fsT')];
+ val aux_ind_Ts = rev (map snd aux_ind_vars);
+ val aux_ind_concl = HOLogic.mk_Trueprop (foldr1 (HOLogic.mk_binop "op &")
+ (map (fn (((i, _), T), tname) =>
+ HOLogic.list_all (aux_ind_vars, make_pred fsT' i T $ Bound 0 $
+ fold_rev (mk_perm aux_ind_Ts) (map Bound (length dt_atomTs downto 1))
+ (Free (tname, T))))
+ (descr'' ~~ recTs ~~ tnames)));
+
+ val fin_set_supp = map (fn s =>
+ at_inst_of thy9 s RS at_fin_set_supp) dt_atoms;
+ val fin_set_fresh = map (fn s =>
+ at_inst_of thy9 s RS at_fin_set_fresh) dt_atoms;
+ val pt1_atoms = map (fn Type (s, _) =>
+ PureThy.get_thm thy9 ("pt_" ^ Long_Name.base_name s ^ "1")) dt_atomTs;
+ val pt2_atoms = map (fn Type (s, _) =>
+ PureThy.get_thm thy9 ("pt_" ^ Long_Name.base_name s ^ "2") RS sym) dt_atomTs;
+ val exists_fresh' = PureThy.get_thms thy9 "exists_fresh'";
+ val fs_atoms = PureThy.get_thms thy9 "fin_supp";
+ val abs_supp = PureThy.get_thms thy9 "abs_supp";
+ val perm_fresh_fresh = PureThy.get_thms thy9 "perm_fresh_fresh";
+ val calc_atm = PureThy.get_thms thy9 "calc_atm";
+ val fresh_atm = PureThy.get_thms thy9 "fresh_atm";
+ val fresh_left = PureThy.get_thms thy9 "fresh_left";
+ val perm_swap = PureThy.get_thms thy9 "perm_swap";
+
+ fun obtain_fresh_name' ths ts T (freshs1, freshs2, ctxt) =
+ let
+ val p = foldr1 HOLogic.mk_prod (ts @ freshs1);
+ val ex = Goal.prove ctxt [] [] (HOLogic.mk_Trueprop
+ (HOLogic.exists_const T $ Abs ("x", T,
+ fresh_const T (fastype_of p) $
+ Bound 0 $ p)))
+ (fn _ => EVERY
+ [resolve_tac exists_fresh' 1,
+ simp_tac (HOL_ss addsimps (supp_prod :: finite_Un :: fs_atoms @
+ fin_set_supp @ ths)) 1]);
+ val (([cx], ths), ctxt') = Obtain.result
+ (fn _ => EVERY
+ [etac exE 1,
+ full_simp_tac (HOL_ss addsimps (fresh_prod :: fresh_atm)) 1,
+ REPEAT (etac conjE 1)])
+ [ex] ctxt
+ in (freshs1 @ [term_of cx], freshs2 @ ths, ctxt') end;
+
+ fun fresh_fresh_inst thy a b =
+ let
+ val T = fastype_of a;
+ val SOME th = find_first (fn th => case prop_of th of
+ _ $ (_ $ (Const (_, Type (_, [U, _])) $ _ $ _)) $ _ => U = T
+ | _ => false) perm_fresh_fresh
+ in
+ Drule.instantiate' []
+ [SOME (cterm_of thy a), NONE, SOME (cterm_of thy b)] th
+ end;
+
+ val fs_cp_sort =
+ map (fs_class_of thy9) dt_atoms @
+ maps (fn s => map (cp_class_of thy9 s) (dt_atoms \ s)) dt_atoms;
+
+ (**********************************************************************
+ The subgoals occurring in the proof of induct_aux have the
+ following parameters:
+
+ x_1 ... x_k p_1 ... p_m z
+
+ where
+
+ x_i : constructor arguments (introduced by weak induction rule)
+ p_i : permutations (one for each atom type in the data type)
+ z : freshness context
+ ***********************************************************************)
+
+ val _ = warning "proving strong induction theorem ...";
+
+ val induct_aux = Goal.prove_global thy9 []
+ (map (augment_sort thy9 fs_cp_sort) ind_prems')
+ (augment_sort thy9 fs_cp_sort ind_concl') (fn {prems, context} =>
+ let
+ val (prems1, prems2) = chop (length dt_atomTs) prems;
+ val ind_ss2 = HOL_ss addsimps
+ finite_Diff :: abs_fresh @ abs_supp @ fs_atoms;
+ val ind_ss1 = ind_ss2 addsimps fresh_left @ calc_atm @
+ fresh_atm @ rev_simps @ app_simps;
+ val ind_ss3 = HOL_ss addsimps abs_fun_eq1 ::
+ abs_perm @ calc_atm @ perm_swap;
+ val ind_ss4 = HOL_basic_ss addsimps fresh_left @ prems1 @
+ fin_set_fresh @ calc_atm;
+ val ind_ss5 = HOL_basic_ss addsimps pt1_atoms;
+ val ind_ss6 = HOL_basic_ss addsimps flat perm_simps';
+ val th = Goal.prove context [] []
+ (augment_sort thy9 fs_cp_sort aux_ind_concl)
+ (fn {context = context1, ...} =>
+ EVERY (indtac dt_induct tnames 1 ::
+ maps (fn ((_, (_, _, constrs)), (_, constrs')) =>
+ map (fn ((cname, cargs), is) =>
+ REPEAT (rtac allI 1) THEN
+ SUBPROOF (fn {prems = iprems, params, concl,
+ context = context2, ...} =>
+ let
+ val concl' = term_of concl;
+ val _ $ (_ $ _ $ u) = concl';
+ val U = fastype_of u;
+ val (xs, params') =
+ chop (length cargs) (map term_of params);
+ val Ts = map fastype_of xs;
+ val cnstr = Const (cname, Ts ---> U);
+ val (pis, z) = split_last params';
+ val mk_pi = fold_rev (mk_perm []) pis;
+ val xs' = partition_cargs is xs;
+ val xs'' = map (fn (ts, u) => (map mk_pi ts, mk_pi u)) xs';
+ val ts = maps (fn (ts, u) => ts @ [u]) xs'';
+ val (freshs1, freshs2, context3) = fold (fn t =>
+ let val T = fastype_of t
+ in obtain_fresh_name' prems1
+ (the (AList.lookup op = fresh_fs T) $ z :: ts) T
+ end) (maps fst xs') ([], [], context2);
+ val freshs1' = unflat (map fst xs') freshs1;
+ val freshs2' = map (Simplifier.simplify ind_ss4)
+ (mk_not_sym freshs2);
+ val ind_ss1' = ind_ss1 addsimps freshs2';
+ val ind_ss3' = ind_ss3 addsimps freshs2';
+ val rename_eq =
+ if forall (null o fst) xs' then []
+ else [Goal.prove context3 [] []
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (list_comb (cnstr, ts),
+ list_comb (cnstr, maps (fn ((bs, t), cs) =>
+ cs @ [fold_rev (mk_perm []) (map perm_of_pair
+ (bs ~~ cs)) t]) (xs'' ~~ freshs1')))))
+ (fn _ => EVERY
+ (simp_tac (HOL_ss addsimps flat inject_thms) 1 ::
+ REPEAT (FIRSTGOAL (rtac conjI)) ::
+ maps (fn ((bs, t), cs) =>
+ if null bs then []
+ else rtac sym 1 :: maps (fn (b, c) =>
+ [rtac trans 1, rtac sym 1,
+ rtac (fresh_fresh_inst thy9 b c) 1,
+ simp_tac ind_ss1' 1,
+ simp_tac ind_ss2 1,
+ simp_tac ind_ss3' 1]) (bs ~~ cs))
+ (xs'' ~~ freshs1')))];
+ val th = Goal.prove context3 [] [] concl' (fn _ => EVERY
+ [simp_tac (ind_ss6 addsimps rename_eq) 1,
+ cut_facts_tac iprems 1,
+ (resolve_tac prems THEN_ALL_NEW
+ SUBGOAL (fn (t, i) => case Logic.strip_assums_concl t of
+ _ $ (Const ("Nominal.fresh", _) $ _ $ _) =>
+ simp_tac ind_ss1' i
+ | _ $ (Const ("Not", _) $ _) =>
+ resolve_tac freshs2' i
+ | _ => asm_simp_tac (HOL_basic_ss addsimps
+ pt2_atoms addsimprocs [perm_simproc]) i)) 1])
+ val final = ProofContext.export context3 context2 [th]
+ in
+ resolve_tac final 1
+ end) context1 1) (constrs ~~ constrs')) (descr'' ~~ ndescr)))
+ in
+ EVERY
+ [cut_facts_tac [th] 1,
+ REPEAT (eresolve_tac [conjE, @{thm allE_Nil}] 1),
+ REPEAT (etac allE 1),
+ REPEAT (TRY (rtac conjI 1) THEN asm_full_simp_tac ind_ss5 1)]
+ end);
+
+ val induct_aux' = Thm.instantiate ([],
+ map (fn (s, v as Var (_, T)) =>
+ (cterm_of thy9 v, cterm_of thy9 (Free (s, T))))
+ (pnames ~~ map head_of (HOLogic.dest_conj
+ (HOLogic.dest_Trueprop (concl_of induct_aux)))) @
+ map (fn (_, f) =>
+ let val f' = Logic.varify f
+ in (cterm_of thy9 f',
+ cterm_of thy9 (Const ("Nominal.supp", fastype_of f')))
+ end) fresh_fs) induct_aux;
+
+ val induct = Goal.prove_global thy9 []
+ (map (augment_sort thy9 fs_cp_sort) ind_prems)
+ (augment_sort thy9 fs_cp_sort ind_concl)
+ (fn {prems, ...} => EVERY
+ [rtac induct_aux' 1,
+ REPEAT (resolve_tac fs_atoms 1),
+ REPEAT ((resolve_tac prems THEN_ALL_NEW
+ (etac meta_spec ORELSE' full_simp_tac (HOL_basic_ss addsimps [fresh_def]))) 1)])
+
+ val (_, thy10) = thy9 |>
+ Sign.add_path big_name |>
+ PureThy.add_thms [((Binding.name "strong_induct'", induct_aux), [])] ||>>
+ PureThy.add_thms [((Binding.name "strong_induct", induct), [case_names_induct])] ||>>
+ PureThy.add_thmss [((Binding.name "strong_inducts", projections induct), [case_names_induct])];
+
+ (**** recursion combinator ****)
+
+ val _ = warning "defining recursion combinator ...";
+
+ val used = List.foldr OldTerm.add_typ_tfree_names [] recTs;
+
+ val (rec_result_Ts', rec_fn_Ts') = DatatypeProp.make_primrec_Ts descr' sorts used;
+
+ val rec_sort = if null dt_atomTs then HOLogic.typeS else
+ Sign.certify_sort thy10 pt_cp_sort;
+
+ val rec_result_Ts = map (fn TFree (s, _) => TFree (s, rec_sort)) rec_result_Ts';
+ val rec_fn_Ts = map (typ_subst_atomic (rec_result_Ts' ~~ rec_result_Ts)) rec_fn_Ts';
+
+ val rec_set_Ts = map (fn (T1, T2) =>
+ rec_fn_Ts @ [T1, T2] ---> HOLogic.boolT) (recTs ~~ rec_result_Ts);
+
+ val big_rec_name = big_name ^ "_rec_set";
+ val rec_set_names' =
+ if length descr'' = 1 then [big_rec_name] else
+ map ((curry (op ^) (big_rec_name ^ "_")) o string_of_int)
+ (1 upto (length descr''));
+ val rec_set_names = map (Sign.full_bname thy10) rec_set_names';
+
+ val rec_fns = map (uncurry (mk_Free "f"))
+ (rec_fn_Ts ~~ (1 upto (length rec_fn_Ts)));
+ val rec_sets' = map (fn c => list_comb (Free c, rec_fns))
+ (rec_set_names' ~~ rec_set_Ts);
+ val rec_sets = map (fn c => list_comb (Const c, rec_fns))
+ (rec_set_names ~~ rec_set_Ts);
+
+ (* introduction rules for graph of recursion function *)
+
+ val rec_preds = map (fn (a, T) =>
+ Free (a, T --> HOLogic.boolT)) (pnames ~~ rec_result_Ts);
+
+ fun mk_fresh3 rs [] = []
+ | mk_fresh3 rs ((p as (ys, z)) :: yss) = List.concat (map (fn y as (_, T) =>
+ List.mapPartial (fn ((_, (_, x)), r as (_, U)) => if z = x then NONE
+ else SOME (HOLogic.mk_Trueprop
+ (fresh_const T U $ Free y $ Free r))) rs) ys) @
+ mk_fresh3 rs yss;
+
+ (* FIXME: avoid collisions with other variable names? *)
+ val rec_ctxt = Free ("z", fsT');
+
+ fun make_rec_intr T p rec_set ((rec_intr_ts, rec_prems, rec_prems',
+ rec_eq_prems, l), ((cname, cargs), idxs)) =
+ let
+ val Ts = map (typ_of_dtyp descr'' sorts) cargs;
+ val frees = map (fn i => "x" ^ string_of_int i) (1 upto length Ts) ~~ Ts;
+ val frees' = partition_cargs idxs frees;
+ val binders = List.concat (map fst frees');
+ val atomTs = distinct op = (maps (map snd o fst) frees');
+ val recs = List.mapPartial
+ (fn ((_, DtRec i), p) => SOME (i, p) | _ => NONE)
+ (partition_cargs idxs cargs ~~ frees');
+ val frees'' = map (fn i => "y" ^ string_of_int i) (1 upto length recs) ~~
+ map (fn (i, _) => List.nth (rec_result_Ts, i)) recs;
+ val prems1 = map (fn ((i, (_, x)), y) => HOLogic.mk_Trueprop
+ (List.nth (rec_sets', i) $ Free x $ Free y)) (recs ~~ frees'');
+ val prems2 =
+ map (fn f => map (fn p as (_, T) => HOLogic.mk_Trueprop
+ (fresh_const T (fastype_of f) $ Free p $ f)) binders) rec_fns;
+ val prems3 = mk_fresh1 [] binders @ mk_fresh2 [] frees';
+ val prems4 = map (fn ((i, _), y) =>
+ HOLogic.mk_Trueprop (List.nth (rec_preds, i) $ Free y)) (recs ~~ frees'');
+ val prems5 = mk_fresh3 (recs ~~ frees'') frees';
+ val prems6 = maps (fn aT => map (fn y as (_, T) => HOLogic.mk_Trueprop
+ (Const ("Finite_Set.finite", HOLogic.mk_setT aT --> HOLogic.boolT) $
+ (Const ("Nominal.supp", T --> HOLogic.mk_setT aT) $ Free y)))
+ frees'') atomTs;
+ val prems7 = map (fn x as (_, T) => HOLogic.mk_Trueprop
+ (fresh_const T fsT' $ Free x $ rec_ctxt)) binders;
+ val result = list_comb (List.nth (rec_fns, l), map Free (frees @ frees''));
+ val result_freshs = map (fn p as (_, T) =>
+ fresh_const T (fastype_of result) $ Free p $ result) binders;
+ val P = HOLogic.mk_Trueprop (p $ result)
+ in
+ (rec_intr_ts @ [Logic.list_implies (List.concat prems2 @ prems3 @ prems1,
+ HOLogic.mk_Trueprop (rec_set $
+ list_comb (Const (cname, Ts ---> T), map Free frees) $ result))],
+ rec_prems @ [list_all_free (frees @ frees'', Logic.list_implies (prems4, P))],
+ rec_prems' @ map (fn fr => list_all_free (frees @ frees'',
+ Logic.list_implies (List.nth (prems2, l) @ prems3 @ prems5 @ prems7 @ prems6 @ [P],
+ HOLogic.mk_Trueprop fr))) result_freshs,
+ rec_eq_prems @ [List.concat prems2 @ prems3],
+ l + 1)
+ end;
+
+ val (rec_intr_ts, rec_prems, rec_prems', rec_eq_prems, _) =
+ Library.foldl (fn (x, ((((d, d'), T), p), rec_set)) =>
+ Library.foldl (make_rec_intr T p rec_set) (x, #3 (snd d) ~~ snd d'))
+ (([], [], [], [], 0), descr'' ~~ ndescr ~~ recTs ~~ rec_preds ~~ rec_sets');
+
+ val ({intrs = rec_intrs, elims = rec_elims, raw_induct = rec_induct, ...}, thy11) =
+ thy10 |>
+ Inductive.add_inductive_global (serial_string ())
+ {quiet_mode = #quiet config, verbose = false, kind = Thm.internalK,
+ alt_name = Binding.name big_rec_name, coind = false, no_elim = false, no_ind = false,
+ skip_mono = true, fork_mono = false}
+ (map (fn (s, T) => ((Binding.name s, T), NoSyn)) (rec_set_names' ~~ rec_set_Ts))
+ (map dest_Free rec_fns)
+ (map (fn x => (Attrib.empty_binding, x)) rec_intr_ts) [] ||>
+ PureThy.hide_fact true (Long_Name.append (Sign.full_bname thy10 big_rec_name) "induct");
+
+ (** equivariance **)
+
+ val fresh_bij = PureThy.get_thms thy11 "fresh_bij";
+ val perm_bij = PureThy.get_thms thy11 "perm_bij";
+
+ val (rec_equiv_thms, rec_equiv_thms') = ListPair.unzip (map (fn aT =>
+ let
+ val permT = mk_permT aT;
+ val pi = Free ("pi", permT);
+ val rec_fns_pi = map (mk_perm [] pi o uncurry (mk_Free "f"))
+ (rec_fn_Ts ~~ (1 upto (length rec_fn_Ts)));
+ val rec_sets_pi = map (fn c => list_comb (Const c, rec_fns_pi))
+ (rec_set_names ~~ rec_set_Ts);
+ val ps = map (fn ((((T, U), R), R'), i) =>
+ let
+ val x = Free ("x" ^ string_of_int i, T);
+ val y = Free ("y" ^ string_of_int i, U)
+ in
+ (R $ x $ y, R' $ mk_perm [] pi x $ mk_perm [] pi y)
+ end) (recTs ~~ rec_result_Ts ~~ rec_sets ~~ rec_sets_pi ~~ (1 upto length recTs));
+ val ths = map (fn th => standard (th RS mp)) (split_conj_thm
+ (Goal.prove_global thy11 [] []
+ (augment_sort thy1 pt_cp_sort
+ (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj (map HOLogic.mk_imp ps))))
+ (fn _ => rtac rec_induct 1 THEN REPEAT
+ (simp_tac (Simplifier.theory_context thy11 HOL_basic_ss
+ addsimps flat perm_simps'
+ addsimprocs [NominalPermeq.perm_simproc_app]) 1 THEN
+ (resolve_tac rec_intrs THEN_ALL_NEW
+ asm_simp_tac (HOL_ss addsimps (fresh_bij @ perm_bij))) 1))))
+ val ths' = map (fn ((P, Q), th) =>
+ Goal.prove_global thy11 [] []
+ (augment_sort thy1 pt_cp_sort
+ (Logic.mk_implies (HOLogic.mk_Trueprop Q, HOLogic.mk_Trueprop P)))
+ (fn _ => dtac (Thm.instantiate ([],
+ [(cterm_of thy11 (Var (("pi", 0), permT)),
+ cterm_of thy11 (Const ("List.rev", permT --> permT) $ pi))]) th) 1 THEN
+ NominalPermeq.perm_simp_tac HOL_ss 1)) (ps ~~ ths)
+ in (ths, ths') end) dt_atomTs);
+
+ (** finite support **)
+
+ val rec_fin_supp_thms = map (fn aT =>
+ let
+ val name = Long_Name.base_name (fst (dest_Type aT));
+ val fs_name = PureThy.get_thm thy11 ("fs_" ^ name ^ "1");
+ val aset = HOLogic.mk_setT aT;
+ val finite = Const ("Finite_Set.finite", aset --> HOLogic.boolT);
+ val fins = map (fn (f, T) => HOLogic.mk_Trueprop
+ (finite $ (Const ("Nominal.supp", T --> aset) $ f)))
+ (rec_fns ~~ rec_fn_Ts)
+ in
+ map (fn th => standard (th RS mp)) (split_conj_thm
+ (Goal.prove_global thy11 []
+ (map (augment_sort thy11 fs_cp_sort) fins)
+ (augment_sort thy11 fs_cp_sort
+ (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
+ (map (fn (((T, U), R), i) =>
+ let
+ val x = Free ("x" ^ string_of_int i, T);
+ val y = Free ("y" ^ string_of_int i, U)
+ in
+ HOLogic.mk_imp (R $ x $ y,
+ finite $ (Const ("Nominal.supp", U --> aset) $ y))
+ end) (recTs ~~ rec_result_Ts ~~ rec_sets ~~
+ (1 upto length recTs))))))
+ (fn {prems = fins, ...} =>
+ (rtac rec_induct THEN_ALL_NEW cut_facts_tac fins) 1 THEN REPEAT
+ (NominalPermeq.finite_guess_tac (HOL_ss addsimps [fs_name]) 1))))
+ end) dt_atomTs;
+
+ (** freshness **)
+
+ val finite_premss = map (fn aT =>
+ map (fn (f, T) => HOLogic.mk_Trueprop
+ (Const ("Finite_Set.finite", HOLogic.mk_setT aT --> HOLogic.boolT) $
+ (Const ("Nominal.supp", T --> HOLogic.mk_setT aT) $ f)))
+ (rec_fns ~~ rec_fn_Ts)) dt_atomTs;
+
+ val rec_fns' = map (augment_sort thy11 fs_cp_sort) rec_fns;
+
+ val rec_fresh_thms = map (fn ((aT, eqvt_ths), finite_prems) =>
+ let
+ val name = Long_Name.base_name (fst (dest_Type aT));
+ val fs_name = PureThy.get_thm thy11 ("fs_" ^ name ^ "1");
+ val a = Free ("a", aT);
+ val freshs = map (fn (f, fT) => HOLogic.mk_Trueprop
+ (fresh_const aT fT $ a $ f)) (rec_fns ~~ rec_fn_Ts)
+ in
+ map (fn (((T, U), R), eqvt_th) =>
+ let
+ val x = Free ("x", augment_sort_typ thy11 fs_cp_sort T);
+ val y = Free ("y", U);
+ val y' = Free ("y'", U)
+ in
+ standard (Goal.prove (ProofContext.init thy11) []
+ (map (augment_sort thy11 fs_cp_sort)
+ (finite_prems @
+ [HOLogic.mk_Trueprop (R $ x $ y),
+ HOLogic.mk_Trueprop (HOLogic.mk_all ("y'", U,
+ HOLogic.mk_imp (R $ x $ y', HOLogic.mk_eq (y', y)))),
+ HOLogic.mk_Trueprop (fresh_const aT T $ a $ x)] @
+ freshs))
+ (HOLogic.mk_Trueprop (fresh_const aT U $ a $ y))
+ (fn {prems, context} =>
+ let
+ val (finite_prems, rec_prem :: unique_prem ::
+ fresh_prems) = chop (length finite_prems) prems;
+ val unique_prem' = unique_prem RS spec RS mp;
+ val unique = [unique_prem', unique_prem' RS sym] MRS trans;
+ val _ $ (_ $ (_ $ S $ _)) $ _ = prop_of supports_fresh;
+ val tuple = foldr1 HOLogic.mk_prod (x :: rec_fns')
+ in EVERY
+ [rtac (Drule.cterm_instantiate
+ [(cterm_of thy11 S,
+ cterm_of thy11 (Const ("Nominal.supp",
+ fastype_of tuple --> HOLogic.mk_setT aT) $ tuple))]
+ supports_fresh) 1,
+ simp_tac (HOL_basic_ss addsimps
+ [supports_def, symmetric fresh_def, fresh_prod]) 1,
+ REPEAT_DETERM (resolve_tac [allI, impI] 1),
+ REPEAT_DETERM (etac conjE 1),
+ rtac unique 1,
+ SUBPROOF (fn {prems = prems', params = [a, b], ...} => EVERY
+ [cut_facts_tac [rec_prem] 1,
+ rtac (Thm.instantiate ([],
+ [(cterm_of thy11 (Var (("pi", 0), mk_permT aT)),
+ cterm_of thy11 (perm_of_pair (term_of a, term_of b)))]) eqvt_th) 1,
+ asm_simp_tac (HOL_ss addsimps
+ (prems' @ perm_swap @ perm_fresh_fresh)) 1]) context 1,
+ rtac rec_prem 1,
+ simp_tac (HOL_ss addsimps (fs_name ::
+ supp_prod :: finite_Un :: finite_prems)) 1,
+ simp_tac (HOL_ss addsimps (symmetric fresh_def ::
+ fresh_prod :: fresh_prems)) 1]
+ end))
+ end) (recTs ~~ rec_result_Ts ~~ rec_sets ~~ eqvt_ths)
+ end) (dt_atomTs ~~ rec_equiv_thms' ~~ finite_premss);
+
+ (** uniqueness **)
+
+ val fun_tuple = foldr1 HOLogic.mk_prod (rec_ctxt :: rec_fns);
+ val fun_tupleT = fastype_of fun_tuple;
+ val rec_unique_frees =
+ DatatypeProp.indexify_names (replicate (length recTs) "x") ~~ recTs;
+ val rec_unique_frees'' = map (fn (s, T) => (s ^ "'", T)) rec_unique_frees;
+ val rec_unique_frees' =
+ DatatypeProp.indexify_names (replicate (length recTs) "y") ~~ rec_result_Ts;
+ val rec_unique_concls = map (fn ((x, U), R) =>
+ Const ("Ex1", (U --> HOLogic.boolT) --> HOLogic.boolT) $
+ Abs ("y", U, R $ Free x $ Bound 0))
+ (rec_unique_frees ~~ rec_result_Ts ~~ rec_sets);
+
+ val induct_aux_rec = Drule.cterm_instantiate
+ (map (pairself (cterm_of thy11) o apsnd (augment_sort thy11 fs_cp_sort))
+ (map (fn (aT, f) => (Logic.varify f, Abs ("z", HOLogic.unitT,
+ Const ("Nominal.supp", fun_tupleT --> HOLogic.mk_setT aT) $ fun_tuple)))
+ fresh_fs @
+ map (fn (((P, T), (x, U)), Q) =>
+ (Var ((P, 0), Logic.varifyT (fsT' --> T --> HOLogic.boolT)),
+ Abs ("z", HOLogic.unitT, absfree (x, U, Q))))
+ (pnames ~~ recTs ~~ rec_unique_frees ~~ rec_unique_concls) @
+ map (fn (s, T) => (Var ((s, 0), Logic.varifyT T), Free (s, T)))
+ rec_unique_frees)) induct_aux;
+
+ fun obtain_fresh_name vs ths rec_fin_supp T (freshs1, freshs2, ctxt) =
+ let
+ val p = foldr1 HOLogic.mk_prod (vs @ freshs1);
+ val ex = Goal.prove ctxt [] [] (HOLogic.mk_Trueprop
+ (HOLogic.exists_const T $ Abs ("x", T,
+ fresh_const T (fastype_of p) $ Bound 0 $ p)))
+ (fn _ => EVERY
+ [cut_facts_tac ths 1,
+ REPEAT_DETERM (dresolve_tac (the (AList.lookup op = rec_fin_supp T)) 1),
+ resolve_tac exists_fresh' 1,
+ asm_simp_tac (HOL_ss addsimps (supp_prod :: finite_Un :: fs_atoms)) 1]);
+ val (([cx], ths), ctxt') = Obtain.result
+ (fn _ => EVERY
+ [etac exE 1,
+ full_simp_tac (HOL_ss addsimps (fresh_prod :: fresh_atm)) 1,
+ REPEAT (etac conjE 1)])
+ [ex] ctxt
+ in (freshs1 @ [term_of cx], freshs2 @ ths, ctxt') end;
+
+ val finite_ctxt_prems = map (fn aT =>
+ HOLogic.mk_Trueprop
+ (Const ("Finite_Set.finite", HOLogic.mk_setT aT --> HOLogic.boolT) $
+ (Const ("Nominal.supp", fsT' --> HOLogic.mk_setT aT) $ rec_ctxt))) dt_atomTs;
+
+ val rec_unique_thms = split_conj_thm (Goal.prove
+ (ProofContext.init thy11) (map fst rec_unique_frees)
+ (map (augment_sort thy11 fs_cp_sort)
+ (List.concat finite_premss @ finite_ctxt_prems @ rec_prems @ rec_prems'))
+ (augment_sort thy11 fs_cp_sort
+ (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj rec_unique_concls)))
+ (fn {prems, context} =>
+ let
+ val k = length rec_fns;
+ val (finite_thss, ths1) = fold_map (fn T => fn xs =>
+ apfst (pair T) (chop k xs)) dt_atomTs prems;
+ val (finite_ctxt_ths, ths2) = chop (length dt_atomTs) ths1;
+ val (P_ind_ths, fcbs) = chop k ths2;
+ val P_ths = map (fn th => th RS mp) (split_conj_thm
+ (Goal.prove context
+ (map fst (rec_unique_frees'' @ rec_unique_frees')) []
+ (augment_sort thy11 fs_cp_sort
+ (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
+ (map (fn (((x, y), S), P) => HOLogic.mk_imp
+ (S $ Free x $ Free y, P $ (Free y)))
+ (rec_unique_frees'' ~~ rec_unique_frees' ~~
+ rec_sets ~~ rec_preds)))))
+ (fn _ =>
+ rtac rec_induct 1 THEN
+ REPEAT ((resolve_tac P_ind_ths THEN_ALL_NEW assume_tac) 1))));
+ val rec_fin_supp_thms' = map
+ (fn (ths, (T, fin_ths)) => (T, map (curry op MRS fin_ths) ths))
+ (rec_fin_supp_thms ~~ finite_thss);
+ in EVERY
+ ([rtac induct_aux_rec 1] @
+ maps (fn ((_, finite_ths), finite_th) =>
+ [cut_facts_tac (finite_th :: finite_ths) 1,
+ asm_simp_tac (HOL_ss addsimps [supp_prod, finite_Un]) 1])
+ (finite_thss ~~ finite_ctxt_ths) @
+ maps (fn ((_, idxss), elim) => maps (fn idxs =>
+ [full_simp_tac (HOL_ss addsimps [symmetric fresh_def, supp_prod, Un_iff]) 1,
+ REPEAT_DETERM (eresolve_tac [conjE, ex1E] 1),
+ rtac ex1I 1,
+ (resolve_tac rec_intrs THEN_ALL_NEW atac) 1,
+ rotate_tac ~1 1,
+ ((DETERM o etac elim) THEN_ALL_NEW full_simp_tac
+ (HOL_ss addsimps List.concat distinct_thms)) 1] @
+ (if null idxs then [] else [hyp_subst_tac 1,
+ SUBPROOF (fn {asms, concl, prems = prems', params, context = context', ...} =>
+ let
+ val SOME prem = find_first (can (HOLogic.dest_eq o
+ HOLogic.dest_Trueprop o prop_of)) prems';
+ val _ $ (_ $ lhs $ rhs) = prop_of prem;
+ val _ $ (_ $ lhs' $ rhs') = term_of concl;
+ val rT = fastype_of lhs';
+ val (c, cargsl) = strip_comb lhs;
+ val cargsl' = partition_cargs idxs cargsl;
+ val boundsl = List.concat (map fst cargsl');
+ val (_, cargsr) = strip_comb rhs;
+ val cargsr' = partition_cargs idxs cargsr;
+ val boundsr = List.concat (map fst cargsr');
+ val (params1, _ :: params2) =
+ chop (length params div 2) (map term_of params);
+ val params' = params1 @ params2;
+ val rec_prems = filter (fn th => case prop_of th of
+ _ $ p => (case head_of p of
+ Const (s, _) => s mem rec_set_names
+ | _ => false)
+ | _ => false) prems';
+ val fresh_prems = filter (fn th => case prop_of th of
+ _ $ (Const ("Nominal.fresh", _) $ _ $ _) => true
+ | _ $ (Const ("Not", _) $ _) => true
+ | _ => false) prems';
+ val Ts = map fastype_of boundsl;
+
+ val _ = warning "step 1: obtaining fresh names";
+ val (freshs1, freshs2, context'') = fold
+ (obtain_fresh_name (rec_ctxt :: rec_fns' @ params')
+ (List.concat (map snd finite_thss) @
+ finite_ctxt_ths @ rec_prems)
+ rec_fin_supp_thms')
+ Ts ([], [], context');
+ val pi1 = map perm_of_pair (boundsl ~~ freshs1);
+ val rpi1 = rev pi1;
+ val pi2 = map perm_of_pair (boundsr ~~ freshs1);
+ val rpi2 = rev pi2;
+
+ val fresh_prems' = mk_not_sym fresh_prems;
+ val freshs2' = mk_not_sym freshs2;
+
+ (** as, bs, cs # K as ts, K bs us **)
+ val _ = warning "step 2: as, bs, cs # K as ts, K bs us";
+ val prove_fresh_ss = HOL_ss addsimps
+ (finite_Diff :: List.concat fresh_thms @
+ fs_atoms @ abs_fresh @ abs_supp @ fresh_atm);
+ (* FIXME: avoid asm_full_simp_tac ? *)
+ fun prove_fresh ths y x = Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (fresh_const
+ (fastype_of x) (fastype_of y) $ x $ y))
+ (fn _ => cut_facts_tac ths 1 THEN asm_full_simp_tac prove_fresh_ss 1);
+ val constr_fresh_thms =
+ map (prove_fresh fresh_prems lhs) boundsl @
+ map (prove_fresh fresh_prems rhs) boundsr @
+ map (prove_fresh freshs2 lhs) freshs1 @
+ map (prove_fresh freshs2 rhs) freshs1;
+
+ (** pi1 o (K as ts) = pi2 o (K bs us) **)
+ val _ = warning "step 3: pi1 o (K as ts) = pi2 o (K bs us)";
+ val pi1_pi2_eq = Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (fold_rev (mk_perm []) pi1 lhs, fold_rev (mk_perm []) pi2 rhs)))
+ (fn _ => EVERY
+ [cut_facts_tac constr_fresh_thms 1,
+ asm_simp_tac (HOL_basic_ss addsimps perm_fresh_fresh) 1,
+ rtac prem 1]);
+
+ (** pi1 o ts = pi2 o us **)
+ val _ = warning "step 4: pi1 o ts = pi2 o us";
+ val pi1_pi2_eqs = map (fn (t, u) =>
+ Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (fold_rev (mk_perm []) pi1 t, fold_rev (mk_perm []) pi2 u)))
+ (fn _ => EVERY
+ [cut_facts_tac [pi1_pi2_eq] 1,
+ asm_full_simp_tac (HOL_ss addsimps
+ (calc_atm @ List.concat perm_simps' @
+ fresh_prems' @ freshs2' @ abs_perm @
+ alpha @ List.concat inject_thms)) 1]))
+ (map snd cargsl' ~~ map snd cargsr');
+
+ (** pi1^-1 o pi2 o us = ts **)
+ val _ = warning "step 5: pi1^-1 o pi2 o us = ts";
+ val rpi1_pi2_eqs = map (fn ((t, u), eq) =>
+ Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (fold_rev (mk_perm []) (rpi1 @ pi2) u, t)))
+ (fn _ => simp_tac (HOL_ss addsimps
+ ((eq RS sym) :: perm_swap)) 1))
+ (map snd cargsl' ~~ map snd cargsr' ~~ pi1_pi2_eqs);
+
+ val (rec_prems1, rec_prems2) =
+ chop (length rec_prems div 2) rec_prems;
+
+ (** (ts, pi1^-1 o pi2 o vs) in rec_set **)
+ val _ = warning "step 6: (ts, pi1^-1 o pi2 o vs) in rec_set";
+ val rec_prems' = map (fn th =>
+ let
+ val _ $ (S $ x $ y) = prop_of th;
+ val Const (s, _) = head_of S;
+ val k = find_index (equal s) rec_set_names;
+ val pi = rpi1 @ pi2;
+ fun mk_pi z = fold_rev (mk_perm []) pi z;
+ fun eqvt_tac p =
+ let
+ val U as Type (_, [Type (_, [T, _])]) = fastype_of p;
+ val l = find_index (equal T) dt_atomTs;
+ val th = List.nth (List.nth (rec_equiv_thms', l), k);
+ val th' = Thm.instantiate ([],
+ [(cterm_of thy11 (Var (("pi", 0), U)),
+ cterm_of thy11 p)]) th;
+ in rtac th' 1 end;
+ val th' = Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (S $ mk_pi x $ mk_pi y))
+ (fn _ => EVERY
+ (map eqvt_tac pi @
+ [simp_tac (HOL_ss addsimps (fresh_prems' @ freshs2' @
+ perm_swap @ perm_fresh_fresh)) 1,
+ rtac th 1]))
+ in
+ Simplifier.simplify
+ (HOL_basic_ss addsimps rpi1_pi2_eqs) th'
+ end) rec_prems2;
+
+ val ihs = filter (fn th => case prop_of th of
+ _ $ (Const ("All", _) $ _) => true | _ => false) prems';
+
+ (** pi1 o rs = pi2 o vs , rs = pi1^-1 o pi2 o vs **)
+ val _ = warning "step 7: pi1 o rs = pi2 o vs , rs = pi1^-1 o pi2 o vs";
+ val rec_eqns = map (fn (th, ih) =>
+ let
+ val th' = th RS (ih RS spec RS mp) RS sym;
+ val _ $ (_ $ lhs $ rhs) = prop_of th';
+ fun strip_perm (_ $ _ $ t) = strip_perm t
+ | strip_perm t = t;
+ in
+ Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (fold_rev (mk_perm []) pi1 lhs,
+ fold_rev (mk_perm []) pi2 (strip_perm rhs))))
+ (fn _ => simp_tac (HOL_basic_ss addsimps
+ (th' :: perm_swap)) 1)
+ end) (rec_prems' ~~ ihs);
+
+ (** as # rs **)
+ val _ = warning "step 8: as # rs";
+ val rec_freshs = List.concat
+ (map (fn (rec_prem, ih) =>
+ let
+ val _ $ (S $ x $ (y as Free (_, T))) =
+ prop_of rec_prem;
+ val k = find_index (equal S) rec_sets;
+ val atoms = List.concat (List.mapPartial (fn (bs, z) =>
+ if z = x then NONE else SOME bs) cargsl')
+ in
+ map (fn a as Free (_, aT) =>
+ let val l = find_index (equal aT) dt_atomTs;
+ in
+ Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (fresh_const aT T $ a $ y))
+ (fn _ => EVERY
+ (rtac (List.nth (List.nth (rec_fresh_thms, l), k)) 1 ::
+ map (fn th => rtac th 1)
+ (snd (List.nth (finite_thss, l))) @
+ [rtac rec_prem 1, rtac ih 1,
+ REPEAT_DETERM (resolve_tac fresh_prems 1)]))
+ end) atoms
+ end) (rec_prems1 ~~ ihs));
+
+ (** as # fK as ts rs , bs # fK bs us vs **)
+ val _ = warning "step 9: as # fK as ts rs , bs # fK bs us vs";
+ fun prove_fresh_result (a as Free (_, aT)) =
+ Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (fresh_const aT rT $ a $ rhs'))
+ (fn _ => EVERY
+ [resolve_tac fcbs 1,
+ REPEAT_DETERM (resolve_tac
+ (fresh_prems @ rec_freshs) 1),
+ REPEAT_DETERM (resolve_tac (maps snd rec_fin_supp_thms') 1
+ THEN resolve_tac rec_prems 1),
+ resolve_tac P_ind_ths 1,
+ REPEAT_DETERM (resolve_tac (P_ths @ rec_prems) 1)]);
+
+ val fresh_results'' = map prove_fresh_result boundsl;
+
+ fun prove_fresh_result'' ((a as Free (_, aT), b), th) =
+ let val th' = Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (fresh_const aT rT $
+ fold_rev (mk_perm []) (rpi2 @ pi1) a $
+ fold_rev (mk_perm []) (rpi2 @ pi1) rhs'))
+ (fn _ => simp_tac (HOL_ss addsimps fresh_bij) 1 THEN
+ rtac th 1)
+ in
+ Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (fresh_const aT rT $ b $ lhs'))
+ (fn _ => EVERY
+ [cut_facts_tac [th'] 1,
+ full_simp_tac (Simplifier.theory_context thy11 HOL_ss
+ addsimps rec_eqns @ pi1_pi2_eqs @ perm_swap
+ addsimprocs [NominalPermeq.perm_simproc_app]) 1,
+ full_simp_tac (HOL_ss addsimps (calc_atm @
+ fresh_prems' @ freshs2' @ perm_fresh_fresh)) 1])
+ end;
+
+ val fresh_results = fresh_results'' @ map prove_fresh_result''
+ (boundsl ~~ boundsr ~~ fresh_results'');
+
+ (** cs # fK as ts rs , cs # fK bs us vs **)
+ val _ = warning "step 10: cs # fK as ts rs , cs # fK bs us vs";
+ fun prove_fresh_result' recs t (a as Free (_, aT)) =
+ Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (fresh_const aT rT $ a $ t))
+ (fn _ => EVERY
+ [cut_facts_tac recs 1,
+ REPEAT_DETERM (dresolve_tac
+ (the (AList.lookup op = rec_fin_supp_thms' aT)) 1),
+ NominalPermeq.fresh_guess_tac
+ (HOL_ss addsimps (freshs2 @
+ fs_atoms @ fresh_atm @
+ List.concat (map snd finite_thss))) 1]);
+
+ val fresh_results' =
+ map (prove_fresh_result' rec_prems1 rhs') freshs1 @
+ map (prove_fresh_result' rec_prems2 lhs') freshs1;
+
+ (** pi1 o (fK as ts rs) = pi2 o (fK bs us vs) **)
+ val _ = warning "step 11: pi1 o (fK as ts rs) = pi2 o (fK bs us vs)";
+ val pi1_pi2_result = Goal.prove context'' [] []
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (fold_rev (mk_perm []) pi1 rhs', fold_rev (mk_perm []) pi2 lhs')))
+ (fn _ => simp_tac (Simplifier.context context'' HOL_ss
+ addsimps pi1_pi2_eqs @ rec_eqns
+ addsimprocs [NominalPermeq.perm_simproc_app]) 1 THEN
+ TRY (simp_tac (HOL_ss addsimps
+ (fresh_prems' @ freshs2' @ calc_atm @ perm_fresh_fresh)) 1));
+
+ val _ = warning "final result";
+ val final = Goal.prove context'' [] [] (term_of concl)
+ (fn _ => cut_facts_tac [pi1_pi2_result RS sym] 1 THEN
+ full_simp_tac (HOL_basic_ss addsimps perm_fresh_fresh @
+ fresh_results @ fresh_results') 1);
+ val final' = ProofContext.export context'' context' [final];
+ val _ = warning "finished!"
+ in
+ resolve_tac final' 1
+ end) context 1])) idxss) (ndescr ~~ rec_elims))
+ end));
+
+ val rec_total_thms = map (fn r => r RS theI') rec_unique_thms;
+
+ (* define primrec combinators *)
+
+ val big_reccomb_name = (space_implode "_" new_type_names) ^ "_rec";
+ val reccomb_names = map (Sign.full_bname thy11)
+ (if length descr'' = 1 then [big_reccomb_name] else
+ (map ((curry (op ^) (big_reccomb_name ^ "_")) o string_of_int)
+ (1 upto (length descr''))));
+ val reccombs = map (fn ((name, T), T') => list_comb
+ (Const (name, rec_fn_Ts @ [T] ---> T'), rec_fns))
+ (reccomb_names ~~ recTs ~~ rec_result_Ts);
+
+ val (reccomb_defs, thy12) =
+ thy11
+ |> Sign.add_consts_i (map (fn ((name, T), T') =>
+ (Binding.name (Long_Name.base_name name), rec_fn_Ts @ [T] ---> T', NoSyn))
+ (reccomb_names ~~ recTs ~~ rec_result_Ts))
+ |> (PureThy.add_defs false o map Thm.no_attributes) (map (fn ((((name, comb), set), T), T') =>
+ (Binding.name (Long_Name.base_name name ^ "_def"), Logic.mk_equals (comb, absfree ("x", T,
+ Const ("The", (T' --> HOLogic.boolT) --> T') $ absfree ("y", T',
+ set $ Free ("x", T) $ Free ("y", T'))))))
+ (reccomb_names ~~ reccombs ~~ rec_sets ~~ recTs ~~ rec_result_Ts));
+
+ (* prove characteristic equations for primrec combinators *)
+
+ val rec_thms = map (fn (prems, concl) =>
+ let
+ val _ $ (_ $ (_ $ x) $ _) = concl;
+ val (_, cargs) = strip_comb x;
+ val ps = map (fn (x as Free (_, T), i) =>
+ (Free ("x" ^ string_of_int i, T), x)) (cargs ~~ (1 upto length cargs));
+ val concl' = subst_atomic_types (rec_result_Ts' ~~ rec_result_Ts) concl;
+ val prems' = List.concat finite_premss @ finite_ctxt_prems @
+ rec_prems @ rec_prems' @ map (subst_atomic ps) prems;
+ fun solve rules prems = resolve_tac rules THEN_ALL_NEW
+ (resolve_tac prems THEN_ALL_NEW atac)
+ in
+ Goal.prove_global thy12 []
+ (map (augment_sort thy12 fs_cp_sort) prems')
+ (augment_sort thy12 fs_cp_sort concl')
+ (fn {prems, ...} => EVERY
+ [rewrite_goals_tac reccomb_defs,
+ rtac the1_equality 1,
+ solve rec_unique_thms prems 1,
+ resolve_tac rec_intrs 1,
+ REPEAT (solve (prems @ rec_total_thms) prems 1)])
+ end) (rec_eq_prems ~~
+ DatatypeProp.make_primrecs new_type_names descr' sorts thy12);
+
+ val dt_infos = map (make_dt_info pdescr sorts induct reccomb_names rec_thms)
+ ((0 upto length descr1 - 1) ~~ descr1 ~~ distinct_thms ~~ inject_thms);
+
+ (* FIXME: theorems are stored in database for testing only *)
+ val (_, thy13) = thy12 |>
+ PureThy.add_thmss
+ [((Binding.name "rec_equiv", List.concat rec_equiv_thms), []),
+ ((Binding.name "rec_equiv'", List.concat rec_equiv_thms'), []),
+ ((Binding.name "rec_fin_supp", List.concat rec_fin_supp_thms), []),
+ ((Binding.name "rec_fresh", List.concat rec_fresh_thms), []),
+ ((Binding.name "rec_unique", map standard rec_unique_thms), []),
+ ((Binding.name "recs", rec_thms), [])] ||>
+ Sign.parent_path ||>
+ map_nominal_datatypes (fold Symtab.update dt_infos);
+
+ in
+ thy13
+ end;
+
+val add_nominal_datatype = gen_add_nominal_datatype Datatype.read_typ;
+
+
+(* FIXME: The following stuff should be exported by Datatype *)
+
+local structure P = OuterParse and K = OuterKeyword in
+
+val datatype_decl =
+ Scan.option (P.$$$ "(" |-- P.name --| P.$$$ ")") -- P.type_args -- P.name -- P.opt_infix --
+ (P.$$$ "=" |-- P.enum1 "|" (P.name -- Scan.repeat P.typ -- P.opt_mixfix));
+
+fun mk_datatype args =
+ let
+ val names = map (fn ((((NONE, _), t), _), _) => t | ((((SOME t, _), _), _), _) => t) args;
+ val specs = map (fn ((((_, vs), t), mx), cons) =>
+ (vs, t, mx, map (fn ((x, y), z) => (x, y, z)) cons)) args;
+ in add_nominal_datatype DatatypeAux.default_datatype_config names specs end;
+
+val _ =
+ OuterSyntax.command "nominal_datatype" "define inductive datatypes" K.thy_decl
+ (P.and_list1 datatype_decl >> (Toplevel.theory o mk_datatype));
+
+end;
+
+end
--- a/src/HOL/Nominal/nominal_atoms.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Nominal/nominal_atoms.ML Fri Jun 19 21:08:07 2009 +0200
@@ -101,7 +101,7 @@
val (_,thy1) =
fold_map (fn ak => fn thy =>
let val dt = ([], Binding.name ak, NoSyn, [(Binding.name ak, [@{typ nat}], NoSyn)])
- val ({inject,case_thms,...},thy1) = DatatypePackage.add_datatype
+ val ({inject,case_thms,...},thy1) = Datatype.add_datatype
DatatypeAux.default_datatype_config [ak] [dt] thy
val inject_flat = flat inject
val ak_type = Type (Sign.intern_type thy1 ak,[])
@@ -191,7 +191,7 @@
thy |> Sign.add_consts_i [(Binding.name ("swap_" ^ ak_name), swapT, NoSyn)]
|> PureThy.add_defs_unchecked true [((Binding.name name, def2),[])]
|> snd
- |> OldPrimrecPackage.add_primrec_unchecked_i "" [(("", def1),[])]
+ |> OldPrimrec.add_primrec_unchecked_i "" [(("", def1),[])]
end) ak_names_types thy1;
(* declares a permutation function for every atom-kind acting *)
@@ -219,7 +219,7 @@
Const (swap_name, swapT) $ x $ (Const (qu_prm_name, prmT) $ xs $ a)));
in
thy |> Sign.add_consts_i [(Binding.name prm_name, mk_permT T --> T --> T, NoSyn)]
- |> OldPrimrecPackage.add_primrec_unchecked_i "" [(("", def1), []),(("", def2), [])]
+ |> OldPrimrec.add_primrec_unchecked_i "" [(("", def1), []),(("", def2), [])]
end) ak_names_types thy3;
(* defines permutation functions for all combinations of atom-kinds; *)
--- a/src/HOL/Nominal/nominal_inductive.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Nominal/nominal_inductive.ML Fri Jun 19 21:08:07 2009 +0200
@@ -53,7 +53,7 @@
fun add_binders thy i (t as (_ $ _)) bs = (case strip_comb t of
(Const (s, T), ts) => (case strip_type T of
(Ts, Type (tname, _)) =>
- (case NominalPackage.get_nominal_datatype thy tname of
+ (case Nominal.get_nominal_datatype thy tname of
NONE => fold (add_binders thy i) ts bs
| SOME {descr, index, ...} => (case AList.lookup op =
(#3 (the (AList.lookup op = descr index))) s of
@@ -148,11 +148,11 @@
let
val thy = ProofContext.theory_of ctxt;
val ({names, ...}, {raw_induct, intrs, elims, ...}) =
- InductivePackage.the_inductive ctxt (Sign.intern_const thy s);
- val ind_params = InductivePackage.params_of raw_induct;
+ Inductive.the_inductive ctxt (Sign.intern_const thy s);
+ val ind_params = Inductive.params_of raw_induct;
val raw_induct = atomize_induct ctxt raw_induct;
val elims = map (atomize_induct ctxt) elims;
- val monos = InductivePackage.get_monos ctxt;
+ val monos = Inductive.get_monos ctxt;
val eqvt_thms = NominalThmDecls.get_eqvt_thms ctxt;
val _ = (case names \\ fold (Term.add_const_names o Thm.prop_of) eqvt_thms [] of
[] => ()
@@ -230,7 +230,7 @@
else NONE) xs @ mk_distinct xs;
fun mk_fresh (x, T) = HOLogic.mk_Trueprop
- (NominalPackage.fresh_const T fsT $ x $ Bound 0);
+ (Nominal.fresh_const T fsT $ x $ Bound 0);
val (prems', prems'') = split_list (map (fn (params, bvars, prems, (p, ts)) =>
let
@@ -254,7 +254,7 @@
val concl = HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
(map (fn (prem, (p, ts)) => HOLogic.mk_imp (prem,
HOLogic.list_all (ind_vars, lift_pred p
- (map (fold_rev (NominalPackage.mk_perm ind_Ts)
+ (map (fold_rev (Nominal.mk_perm ind_Ts)
(map Bound (length atomTs downto 1))) ts)))) concls));
val concl' = HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
@@ -268,7 +268,7 @@
else map_term (split_conj (K o I) names) prem prem) prems, q))))
(mk_distinct bvars @
maps (fn (t, T) => map (fn (u, U) => HOLogic.mk_Trueprop
- (NominalPackage.fresh_const U T $ u $ t)) bvars)
+ (Nominal.fresh_const U T $ u $ t)) bvars)
(ts ~~ binder_types (fastype_of p)))) prems;
val perm_pi_simp = PureThy.get_thms thy "perm_pi_simp";
@@ -296,7 +296,7 @@
val p = foldr1 HOLogic.mk_prod (map protect ts @ freshs1);
val ex = Goal.prove ctxt [] [] (HOLogic.mk_Trueprop
(HOLogic.exists_const T $ Abs ("x", T,
- NominalPackage.fresh_const T (fastype_of p) $
+ Nominal.fresh_const T (fastype_of p) $
Bound 0 $ p)))
(fn _ => EVERY
[resolve_tac exists_fresh' 1,
@@ -325,13 +325,13 @@
(fn (Bound i, T) => (nth params' (length params' - i), T)
| (t, T) => (t, T)) bvars;
val pi_bvars = map (fn (t, _) =>
- fold_rev (NominalPackage.mk_perm []) pis t) bvars';
+ fold_rev (Nominal.mk_perm []) pis t) bvars';
val (P, ts) = strip_comb (HOLogic.dest_Trueprop (term_of concl));
val (freshs1, freshs2, ctxt'') = fold
(obtain_fresh_name (ts @ pi_bvars))
(map snd bvars') ([], [], ctxt');
- val freshs2' = NominalPackage.mk_not_sym freshs2;
- val pis' = map NominalPackage.perm_of_pair (pi_bvars ~~ freshs1);
+ val freshs2' = Nominal.mk_not_sym freshs2;
+ val pis' = map Nominal.perm_of_pair (pi_bvars ~~ freshs1);
fun concat_perm pi1 pi2 =
let val T = fastype_of pi1
in if T = fastype_of pi2 then
@@ -343,11 +343,11 @@
(Vartab.empty, Vartab.empty);
val ihyp' = Thm.instantiate ([], map (pairself (cterm_of thy))
(map (Envir.subst_vars env) vs ~~
- map (fold_rev (NominalPackage.mk_perm [])
+ map (fold_rev (Nominal.mk_perm [])
(rev pis' @ pis)) params' @ [z])) ihyp;
fun mk_pi th =
Simplifier.simplify (HOL_basic_ss addsimps [@{thm id_apply}]
- addsimprocs [NominalPackage.perm_simproc])
+ addsimprocs [Nominal.perm_simproc])
(Simplifier.simplify eqvt_ss
(fold_rev (mk_perm_bool o cterm_of thy)
(rev pis' @ pis) th));
@@ -369,13 +369,13 @@
| _ $ (_ $ (_ $ lhs $ rhs)) =>
(curry (HOLogic.mk_not o HOLogic.mk_eq), lhs, rhs));
val th'' = Goal.prove ctxt'' [] [] (HOLogic.mk_Trueprop
- (bop (fold_rev (NominalPackage.mk_perm []) pis lhs)
- (fold_rev (NominalPackage.mk_perm []) pis rhs)))
+ (bop (fold_rev (Nominal.mk_perm []) pis lhs)
+ (fold_rev (Nominal.mk_perm []) pis rhs)))
(fn _ => simp_tac (HOL_basic_ss addsimps
(fresh_bij @ perm_bij)) 1 THEN rtac th' 1)
in Simplifier.simplify (eqvt_ss addsimps fresh_atm) th'' end)
vc_compat_ths;
- val vc_compat_ths'' = NominalPackage.mk_not_sym vc_compat_ths';
+ val vc_compat_ths'' = Nominal.mk_not_sym vc_compat_ths';
(** Since swap_simps simplifies (pi :: 'a prm) o (x :: 'b) to x **)
(** we have to pre-simplify the rewrite rules **)
val swap_simps_ss = HOL_ss addsimps swap_simps @
@@ -383,14 +383,14 @@
(vc_compat_ths'' @ freshs2');
val th = Goal.prove ctxt'' [] []
(HOLogic.mk_Trueprop (list_comb (P $ hd ts,
- map (fold (NominalPackage.mk_perm []) pis') (tl ts))))
+ map (fold (Nominal.mk_perm []) pis') (tl ts))))
(fn _ => EVERY ([simp_tac eqvt_ss 1, rtac ihyp' 1,
REPEAT_DETERM_N (nprems_of ihyp - length gprems)
(simp_tac swap_simps_ss 1),
REPEAT_DETERM_N (length gprems)
(simp_tac (HOL_basic_ss
addsimps [inductive_forall_def']
- addsimprocs [NominalPackage.perm_simproc]) 1 THEN
+ addsimprocs [Nominal.perm_simproc]) 1 THEN
resolve_tac gprems2 1)]));
val final = Goal.prove ctxt'' [] [] (term_of concl)
(fn _ => cut_facts_tac [th] 1 THEN full_simp_tac (HOL_ss
@@ -435,7 +435,7 @@
((ps, qs, is, map (curry subst_bounds (rev ts)) prems), ctxt')
end) (prems ~~ avoids) ctxt')
end)
- (InductivePackage.partition_rules' raw_induct (intrs ~~ avoids') ~~
+ (Inductive.partition_rules' raw_induct (intrs ~~ avoids') ~~
elims);
val cases_prems' =
@@ -448,7 +448,7 @@
(Logic.list_implies
(mk_distinct qs @
maps (fn (t, T) => map (fn u => HOLogic.mk_Trueprop
- (NominalPackage.fresh_const T (fastype_of u) $ t $ u))
+ (Nominal.fresh_const T (fastype_of u) $ t $ u))
args) qs,
HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
(map HOLogic.dest_Trueprop prems))),
@@ -499,13 +499,13 @@
chop (length vc_compat_ths - length args * length qs)
(map (first_order_mrs hyps2) vc_compat_ths);
val vc_compat_ths' =
- NominalPackage.mk_not_sym vc_compat_ths1 @
+ Nominal.mk_not_sym vc_compat_ths1 @
flat (fst (fold_map inst_fresh hyps1 vc_compat_ths2));
val (freshs1, freshs2, ctxt3) = fold
(obtain_fresh_name (args @ map fst qs @ params'))
(map snd qs) ([], [], ctxt2);
- val freshs2' = NominalPackage.mk_not_sym freshs2;
- val pis = map (NominalPackage.perm_of_pair)
+ val freshs2' = Nominal.mk_not_sym freshs2;
+ val pis = map (Nominal.perm_of_pair)
((freshs1 ~~ map fst qs) @ (params' ~~ freshs1));
val mk_pis = fold_rev mk_perm_bool (map (cterm_of thy) pis);
val obj = cterm_of thy (foldr1 HOLogic.mk_conj (map (map_aterms
@@ -513,7 +513,7 @@
if x mem args then x
else (case AList.lookup op = tab x of
SOME y => y
- | NONE => fold_rev (NominalPackage.mk_perm []) pis x)
+ | NONE => fold_rev (Nominal.mk_perm []) pis x)
| x => x) o HOLogic.dest_Trueprop o prop_of) case_hyps));
val inst = Thm.first_order_match (Thm.dest_arg
(Drule.strip_imp_concl (hd (cprems_of case_hyp))), obj);
@@ -522,7 +522,7 @@
rtac (Thm.instantiate inst case_hyp) 1 THEN
SUBPROOF (fn {prems = fresh_hyps, ...} =>
let
- val fresh_hyps' = NominalPackage.mk_not_sym fresh_hyps;
+ val fresh_hyps' = Nominal.mk_not_sym fresh_hyps;
val case_ss = cases_eqvt_ss addsimps freshs2' @
simp_fresh_atm (vc_compat_ths' @ fresh_hyps');
val fresh_fresh_ss = case_ss addsimps perm_fresh_fresh;
@@ -548,13 +548,13 @@
val rec_name = space_implode "_" (map Long_Name.base_name names);
val rec_qualified = Binding.qualify false rec_name;
val ind_case_names = RuleCases.case_names induct_cases;
- val induct_cases' = InductivePackage.partition_rules' raw_induct
+ val induct_cases' = Inductive.partition_rules' raw_induct
(intrs ~~ induct_cases);
val thss' = map (map atomize_intr) thss;
- val thsss = InductivePackage.partition_rules' raw_induct (intrs ~~ thss');
+ val thsss = Inductive.partition_rules' raw_induct (intrs ~~ thss');
val strong_raw_induct =
- mk_ind_proof ctxt thss' |> InductivePackage.rulify;
- val strong_cases = map (mk_cases_proof ##> InductivePackage.rulify)
+ mk_ind_proof ctxt thss' |> Inductive.rulify;
+ val strong_cases = map (mk_cases_proof ##> Inductive.rulify)
(thsss ~~ elims ~~ cases_prems ~~ cases_prems');
val strong_induct =
if length names > 1 then
@@ -587,17 +587,17 @@
let
val thy = ProofContext.theory_of ctxt;
val ({names, ...}, {raw_induct, intrs, elims, ...}) =
- InductivePackage.the_inductive ctxt (Sign.intern_const thy s);
+ Inductive.the_inductive ctxt (Sign.intern_const thy s);
val raw_induct = atomize_induct ctxt raw_induct;
val elims = map (atomize_induct ctxt) elims;
val intrs = map atomize_intr intrs;
- val monos = InductivePackage.get_monos ctxt;
- val intrs' = InductivePackage.unpartition_rules intrs
+ val monos = Inductive.get_monos ctxt;
+ val intrs' = Inductive.unpartition_rules intrs
(map (fn (((s, ths), (_, k)), th) =>
- (s, ths ~~ InductivePackage.infer_intro_vars th k ths))
- (InductivePackage.partition_rules raw_induct intrs ~~
- InductivePackage.arities_of raw_induct ~~ elims));
- val k = length (InductivePackage.params_of raw_induct);
+ (s, ths ~~ Inductive.infer_intro_vars th k ths))
+ (Inductive.partition_rules raw_induct intrs ~~
+ Inductive.arities_of raw_induct ~~ elims));
+ val k = length (Inductive.params_of raw_induct);
val atoms' = NominalAtoms.atoms_of thy;
val atoms =
if null xatoms then atoms' else
@@ -635,7 +635,7 @@
val prems'' = map (fn th => Simplifier.simplify eqvt_ss
(mk_perm_bool (cterm_of thy pi) th)) prems';
val intr' = Drule.cterm_instantiate (map (cterm_of thy) vs ~~
- map (cterm_of thy o NominalPackage.mk_perm [] pi o term_of) params)
+ map (cterm_of thy o Nominal.mk_perm [] pi o term_of) params)
intr
in (rtac intr' THEN_ALL_NEW (TRY o resolve_tac prems'')) 1
end) ctxt' 1 st
@@ -655,7 +655,7 @@
val (ts1, ts2) = chop k ts
in
HOLogic.mk_imp (p, list_comb (h, ts1 @
- map (NominalPackage.mk_perm [] pi') ts2))
+ map (Nominal.mk_perm [] pi') ts2))
end) ps)))
(fn {context, ...} => EVERY (rtac raw_induct 1 :: map (fn intr_vs =>
full_simp_tac eqvt_ss 1 THEN
--- a/src/HOL/Nominal/nominal_inductive2.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Nominal/nominal_inductive2.ML Fri Jun 19 21:08:07 2009 +0200
@@ -56,7 +56,7 @@
fun add_binders thy i (t as (_ $ _)) bs = (case strip_comb t of
(Const (s, T), ts) => (case strip_type T of
(Ts, Type (tname, _)) =>
- (case NominalPackage.get_nominal_datatype thy tname of
+ (case Nominal.get_nominal_datatype thy tname of
NONE => fold (add_binders thy i) ts bs
| SOME {descr, index, ...} => (case AList.lookup op =
(#3 (the (AList.lookup op = descr index))) s of
@@ -154,11 +154,11 @@
let
val thy = ProofContext.theory_of ctxt;
val ({names, ...}, {raw_induct, intrs, elims, ...}) =
- InductivePackage.the_inductive ctxt (Sign.intern_const thy s);
- val ind_params = InductivePackage.params_of raw_induct;
+ Inductive.the_inductive ctxt (Sign.intern_const thy s);
+ val ind_params = Inductive.params_of raw_induct;
val raw_induct = atomize_induct ctxt raw_induct;
val elims = map (atomize_induct ctxt) elims;
- val monos = InductivePackage.get_monos ctxt;
+ val monos = Inductive.get_monos ctxt;
val eqvt_thms = NominalThmDecls.get_eqvt_thms ctxt;
val _ = (case names \\ fold (Term.add_const_names o Thm.prop_of) eqvt_thms [] of
[] => ()
@@ -249,7 +249,7 @@
| lift_prem t = t;
fun mk_fresh (x, T) = HOLogic.mk_Trueprop
- (NominalPackage.fresh_star_const T fsT $ x $ Bound 0);
+ (Nominal.fresh_star_const T fsT $ x $ Bound 0);
val (prems', prems'') = split_list (map (fn (params, sets, prems, (p, ts)) =>
let
@@ -270,7 +270,7 @@
val concl = HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
(map (fn (prem, (p, ts)) => HOLogic.mk_imp (prem,
HOLogic.list_all (ind_vars, lift_pred p
- (map (fold_rev (NominalPackage.mk_perm ind_Ts)
+ (map (fold_rev (Nominal.mk_perm ind_Ts)
(map Bound (length atomTs downto 1))) ts)))) concls));
val concl' = HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
@@ -283,7 +283,7 @@
if null (preds_of ps prem) then SOME prem
else map_term (split_conj (K o I) names) prem prem) prems, q))))
(maps (fn (t, T) => map (fn (u, U) => HOLogic.mk_Trueprop
- (NominalPackage.fresh_star_const U T $ u $ t)) sets)
+ (Nominal.fresh_star_const U T $ u $ t)) sets)
(ts ~~ binder_types (fastype_of p)) @
map (fn (u, U) => HOLogic.mk_Trueprop (Const (@{const_name finite},
HOLogic.mk_setT U --> HOLogic.boolT) $ u)) sets) |>
@@ -339,7 +339,7 @@
val th2' =
Goal.prove ctxt [] []
(list_all (map (pair "pi") pTs, HOLogic.mk_Trueprop
- (f $ fold_rev (NominalPackage.mk_perm (rev pTs))
+ (f $ fold_rev (Nominal.mk_perm (rev pTs))
(pis1 @ pi :: pis2) l $ r)))
(fn _ => cut_facts_tac [th2] 1 THEN
full_simp_tac (HOL_basic_ss addsimps perm_set_forget) 1) |>
@@ -364,7 +364,7 @@
val params' = map term_of cparams'
val sets' = map (apfst (curry subst_bounds (rev params'))) sets;
val pi_sets = map (fn (t, _) =>
- fold_rev (NominalPackage.mk_perm []) pis t) sets';
+ fold_rev (Nominal.mk_perm []) pis t) sets';
val (P, ts) = strip_comb (HOLogic.dest_Trueprop (term_of concl));
val gprems1 = List.mapPartial (fn (th, t) =>
if null (preds_of ps t) then SOME th
@@ -380,7 +380,7 @@
in
Goal.prove ctxt' [] []
(HOLogic.mk_Trueprop (list_comb (h,
- map (fold_rev (NominalPackage.mk_perm []) pis) ts)))
+ map (fold_rev (Nominal.mk_perm []) pis) ts)))
(fn _ => simp_tac (HOL_basic_ss addsimps
(fresh_star_bij @ finite_ineq)) 1 THEN rtac th' 1)
end) vc_compat_ths vc_compat_vs;
@@ -400,11 +400,11 @@
end;
val pis'' = fold_rev (concat_perm #> map) pis' pis;
val ihyp' = inst_params thy vs_ihypt ihyp
- (map (fold_rev (NominalPackage.mk_perm [])
+ (map (fold_rev (Nominal.mk_perm [])
(pis' @ pis) #> cterm_of thy) params' @ [cterm_of thy z]);
fun mk_pi th =
Simplifier.simplify (HOL_basic_ss addsimps [@{thm id_apply}]
- addsimprocs [NominalPackage.perm_simproc])
+ addsimprocs [Nominal.perm_simproc])
(Simplifier.simplify eqvt_ss
(fold_rev (mk_perm_bool o cterm_of thy)
(pis' @ pis) th));
@@ -419,13 +419,13 @@
(fresh_ths2 ~~ sets);
val th = Goal.prove ctxt'' [] []
(HOLogic.mk_Trueprop (list_comb (P $ hd ts,
- map (fold_rev (NominalPackage.mk_perm []) pis') (tl ts))))
+ map (fold_rev (Nominal.mk_perm []) pis') (tl ts))))
(fn _ => EVERY ([simp_tac eqvt_ss 1, rtac ihyp' 1] @
map (fn th => rtac th 1) fresh_ths3 @
[REPEAT_DETERM_N (length gprems)
(simp_tac (HOL_basic_ss
addsimps [inductive_forall_def']
- addsimprocs [NominalPackage.perm_simproc]) 1 THEN
+ addsimprocs [Nominal.perm_simproc]) 1 THEN
resolve_tac gprems2 1)]));
val final = Goal.prove ctxt'' [] [] (term_of concl)
(fn _ => cut_facts_tac [th] 1 THEN full_simp_tac (HOL_ss
@@ -450,12 +450,12 @@
val rec_name = space_implode "_" (map Long_Name.base_name names);
val rec_qualified = Binding.qualify false rec_name;
val ind_case_names = RuleCases.case_names induct_cases;
- val induct_cases' = InductivePackage.partition_rules' raw_induct
+ val induct_cases' = Inductive.partition_rules' raw_induct
(intrs ~~ induct_cases);
val thss' = map (map atomize_intr) thss;
- val thsss = InductivePackage.partition_rules' raw_induct (intrs ~~ thss');
+ val thsss = Inductive.partition_rules' raw_induct (intrs ~~ thss');
val strong_raw_induct =
- mk_ind_proof ctxt thss' |> InductivePackage.rulify;
+ mk_ind_proof ctxt thss' |> Inductive.rulify;
val strong_induct =
if length names > 1 then
(strong_raw_induct, [ind_case_names, RuleCases.consumes 0])
--- a/src/HOL/Nominal/nominal_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2095 +0,0 @@
-(* Title: HOL/Nominal/nominal_package.ML
- Author: Stefan Berghofer and Christian Urban, TU Muenchen
-
-Nominal datatype package for Isabelle/HOL.
-*)
-
-signature NOMINAL_PACKAGE =
-sig
- val add_nominal_datatype : DatatypeAux.datatype_config -> string list ->
- (string list * bstring * mixfix *
- (bstring * string list * mixfix) list) list -> theory -> theory
- type descr
- type nominal_datatype_info
- val get_nominal_datatypes : theory -> nominal_datatype_info Symtab.table
- val get_nominal_datatype : theory -> string -> nominal_datatype_info option
- val mk_perm: typ list -> term -> term -> term
- val perm_of_pair: term * term -> term
- val mk_not_sym: thm list -> thm list
- val perm_simproc: simproc
- val fresh_const: typ -> typ -> term
- val fresh_star_const: typ -> typ -> term
-end
-
-structure NominalPackage : NOMINAL_PACKAGE =
-struct
-
-val finite_emptyI = thm "finite.emptyI";
-val finite_Diff = thm "finite_Diff";
-val finite_Un = thm "finite_Un";
-val Un_iff = thm "Un_iff";
-val In0_eq = thm "In0_eq";
-val In1_eq = thm "In1_eq";
-val In0_not_In1 = thm "In0_not_In1";
-val In1_not_In0 = thm "In1_not_In0";
-val Un_assoc = thm "Un_assoc";
-val Collect_disj_eq = thm "Collect_disj_eq";
-val empty_def = thm "empty_def";
-val empty_iff = thm "empty_iff";
-
-open DatatypeAux;
-open NominalAtoms;
-
-(** FIXME: DatatypePackage should export this function **)
-
-local
-
-fun dt_recs (DtTFree _) = []
- | dt_recs (DtType (_, dts)) = List.concat (map dt_recs dts)
- | dt_recs (DtRec i) = [i];
-
-fun dt_cases (descr: descr) (_, args, constrs) =
- let
- fun the_bname i = Long_Name.base_name (#1 (valOf (AList.lookup (op =) descr i)));
- val bnames = map the_bname (distinct op = (List.concat (map dt_recs args)));
- in map (fn (c, _) => space_implode "_" (Long_Name.base_name c :: bnames)) constrs end;
-
-
-fun induct_cases descr =
- DatatypeProp.indexify_names (List.concat (map (dt_cases descr) (map #2 descr)));
-
-fun exhaust_cases descr i = dt_cases descr (valOf (AList.lookup (op =) descr i));
-
-in
-
-fun mk_case_names_induct descr = RuleCases.case_names (induct_cases descr);
-
-fun mk_case_names_exhausts descr new =
- map (RuleCases.case_names o exhaust_cases descr o #1)
- (List.filter (fn ((_, (name, _, _))) => name mem_string new) descr);
-
-end;
-
-(* theory data *)
-
-type descr = (int * (string * dtyp list * (string * (dtyp list * dtyp) list) list)) list;
-
-type nominal_datatype_info =
- {index : int,
- descr : descr,
- sorts : (string * sort) list,
- rec_names : string list,
- rec_rewrites : thm list,
- induction : thm,
- distinct : thm list,
- inject : thm list};
-
-structure NominalDatatypesData = TheoryDataFun
-(
- type T = nominal_datatype_info Symtab.table;
- val empty = Symtab.empty;
- val copy = I;
- val extend = I;
- fun merge _ tabs : T = Symtab.merge (K true) tabs;
-);
-
-val get_nominal_datatypes = NominalDatatypesData.get;
-val put_nominal_datatypes = NominalDatatypesData.put;
-val map_nominal_datatypes = NominalDatatypesData.map;
-val get_nominal_datatype = Symtab.lookup o get_nominal_datatypes;
-
-
-(**** make datatype info ****)
-
-fun make_dt_info descr sorts induct reccomb_names rec_thms
- (((i, (_, (tname, _, _))), distinct), inject) =
- (tname,
- {index = i,
- descr = descr,
- sorts = sorts,
- rec_names = reccomb_names,
- rec_rewrites = rec_thms,
- induction = induct,
- distinct = distinct,
- inject = inject});
-
-(*******************************)
-
-val (_ $ (_ $ (_ $ (distinct_f $ _) $ _))) = hd (prems_of distinct_lemma);
-
-
-(** simplification procedure for sorting permutations **)
-
-val dj_cp = thm "dj_cp";
-
-fun dest_permT (Type ("fun", [Type ("List.list", [Type ("*", [T, _])]),
- Type ("fun", [_, U])])) = (T, U);
-
-fun permTs_of (Const ("Nominal.perm", T) $ t $ u) = fst (dest_permT T) :: permTs_of u
- | permTs_of _ = [];
-
-fun perm_simproc' thy ss (Const ("Nominal.perm", T) $ t $ (u as Const ("Nominal.perm", U) $ r $ s)) =
- let
- val (aT as Type (a, []), S) = dest_permT T;
- val (bT as Type (b, []), _) = dest_permT U
- in if aT mem permTs_of u andalso aT <> bT then
- let
- val cp = cp_inst_of thy a b;
- val dj = dj_thm_of thy b a;
- val dj_cp' = [cp, dj] MRS dj_cp;
- val cert = SOME o cterm_of thy
- in
- SOME (mk_meta_eq (Drule.instantiate' [SOME (ctyp_of thy S)]
- [cert t, cert r, cert s] dj_cp'))
- end
- else NONE
- end
- | perm_simproc' thy ss _ = NONE;
-
-val perm_simproc =
- Simplifier.simproc (the_context ()) "perm_simp" ["pi1 \<bullet> (pi2 \<bullet> x)"] perm_simproc';
-
-val meta_spec = thm "meta_spec";
-
-fun projections rule =
- ProjectRule.projections (ProofContext.init (Thm.theory_of_thm rule)) rule
- |> map (standard #> RuleCases.save rule);
-
-val supp_prod = thm "supp_prod";
-val fresh_prod = thm "fresh_prod";
-val supports_fresh = thm "supports_fresh";
-val supports_def = thm "Nominal.supports_def";
-val fresh_def = thm "fresh_def";
-val supp_def = thm "supp_def";
-val rev_simps = thms "rev.simps";
-val app_simps = thms "append.simps";
-val at_fin_set_supp = thm "at_fin_set_supp";
-val at_fin_set_fresh = thm "at_fin_set_fresh";
-val abs_fun_eq1 = thm "abs_fun_eq1";
-
-val collect_simp = rewrite_rule [mk_meta_eq mem_Collect_eq];
-
-fun mk_perm Ts t u =
- let
- val T = fastype_of1 (Ts, t);
- val U = fastype_of1 (Ts, u)
- in Const ("Nominal.perm", T --> U --> U) $ t $ u end;
-
-fun perm_of_pair (x, y) =
- let
- val T = fastype_of x;
- val pT = mk_permT T
- in Const ("List.list.Cons", HOLogic.mk_prodT (T, T) --> pT --> pT) $
- HOLogic.mk_prod (x, y) $ Const ("List.list.Nil", pT)
- end;
-
-fun mk_not_sym ths = maps (fn th => case prop_of th of
- _ $ (Const ("Not", _) $ (Const ("op =", _) $ _ $ _)) => [th, th RS not_sym]
- | _ => [th]) ths;
-
-fun fresh_const T U = Const ("Nominal.fresh", T --> U --> HOLogic.boolT);
-fun fresh_star_const T U =
- Const ("Nominal.fresh_star", HOLogic.mk_setT T --> U --> HOLogic.boolT);
-
-fun gen_add_nominal_datatype prep_typ config new_type_names dts thy =
- let
- (* this theory is used just for parsing *)
-
- val tmp_thy = thy |>
- Theory.copy |>
- Sign.add_types (map (fn (tvs, tname, mx, _) =>
- (Binding.name tname, length tvs, mx)) dts);
-
- val atoms = atoms_of thy;
-
- fun prep_constr ((constrs, sorts), (cname, cargs, mx)) =
- let val (cargs', sorts') = Library.foldl (prep_typ tmp_thy) (([], sorts), cargs)
- in (constrs @ [(cname, cargs', mx)], sorts') end
-
- fun prep_dt_spec ((dts, sorts), (tvs, tname, mx, constrs)) =
- let val (constrs', sorts') = Library.foldl prep_constr (([], sorts), constrs)
- in (dts @ [(tvs, tname, mx, constrs')], sorts') end
-
- val (dts', sorts) = Library.foldl prep_dt_spec (([], []), dts);
- val tyvars = map (map (fn s =>
- (s, the (AList.lookup (op =) sorts s))) o #1) dts';
-
- fun inter_sort thy S S' = Type.inter_sort (Sign.tsig_of thy) (S, S');
- fun augment_sort_typ thy S =
- let val S = Sign.certify_sort thy S
- in map_type_tfree (fn (s, S') => TFree (s,
- if member (op = o apsnd fst) sorts s then inter_sort thy S S' else S'))
- end;
- fun augment_sort thy S = map_types (augment_sort_typ thy S);
-
- val types_syntax = map (fn (tvs, tname, mx, constrs) => (tname, mx)) dts';
- val constr_syntax = map (fn (tvs, tname, mx, constrs) =>
- map (fn (cname, cargs, mx) => (cname, mx)) constrs) dts';
-
- val ps = map (fn (_, n, _, _) =>
- (Sign.full_bname tmp_thy n, Sign.full_bname tmp_thy (n ^ "_Rep"))) dts;
- val rps = map Library.swap ps;
-
- fun replace_types (Type ("Nominal.ABS", [T, U])) =
- Type ("fun", [T, Type ("Nominal.noption", [replace_types U])])
- | replace_types (Type (s, Ts)) =
- Type (getOpt (AList.lookup op = ps s, s), map replace_types Ts)
- | replace_types T = T;
-
- val dts'' = map (fn (tvs, tname, mx, constrs) => (tvs, Binding.name (tname ^ "_Rep"), NoSyn,
- map (fn (cname, cargs, mx) => (Binding.name (cname ^ "_Rep"),
- map replace_types cargs, NoSyn)) constrs)) dts';
-
- val new_type_names' = map (fn n => n ^ "_Rep") new_type_names;
- val full_new_type_names' = map (Sign.full_bname thy) new_type_names';
-
- val ({induction, ...},thy1) =
- DatatypePackage.add_datatype config new_type_names' dts'' thy;
-
- val SOME {descr, ...} = Symtab.lookup
- (DatatypePackage.get_datatypes thy1) (hd full_new_type_names');
- fun nth_dtyp i = typ_of_dtyp descr sorts (DtRec i);
-
- val big_name = space_implode "_" new_type_names;
-
-
- (**** define permutation functions ****)
-
- val permT = mk_permT (TFree ("'x", HOLogic.typeS));
- val pi = Free ("pi", permT);
- val perm_types = map (fn (i, _) =>
- let val T = nth_dtyp i
- in permT --> T --> T end) descr;
- val perm_names' = DatatypeProp.indexify_names (map (fn (i, _) =>
- "perm_" ^ name_of_typ (nth_dtyp i)) descr);
- val perm_names = replicate (length new_type_names) "Nominal.perm" @
- map (Sign.full_bname thy1) (List.drop (perm_names', length new_type_names));
- val perm_names_types = perm_names ~~ perm_types;
- val perm_names_types' = perm_names' ~~ perm_types;
-
- val perm_eqs = maps (fn (i, (_, _, constrs)) =>
- let val T = nth_dtyp i
- in map (fn (cname, dts) =>
- let
- val Ts = map (typ_of_dtyp descr sorts) dts;
- val names = Name.variant_list ["pi"] (DatatypeProp.make_tnames Ts);
- val args = map Free (names ~~ Ts);
- val c = Const (cname, Ts ---> T);
- fun perm_arg (dt, x) =
- let val T = type_of x
- in if is_rec_type dt then
- let val (Us, _) = strip_type T
- in list_abs (map (pair "x") Us,
- Free (nth perm_names_types' (body_index dt)) $ pi $
- list_comb (x, map (fn (i, U) =>
- Const ("Nominal.perm", permT --> U --> U) $
- (Const ("List.rev", permT --> permT) $ pi) $
- Bound i) ((length Us - 1 downto 0) ~~ Us)))
- end
- else Const ("Nominal.perm", permT --> T --> T) $ pi $ x
- end;
- in
- (Attrib.empty_binding, HOLogic.mk_Trueprop (HOLogic.mk_eq
- (Free (nth perm_names_types' i) $
- Free ("pi", mk_permT (TFree ("'x", HOLogic.typeS))) $
- list_comb (c, args),
- list_comb (c, map perm_arg (dts ~~ args)))))
- end) constrs
- end) descr;
-
- val (perm_simps, thy2) =
- PrimrecPackage.add_primrec_overloaded
- (map (fn (s, sT) => (s, sT, false))
- (List.take (perm_names' ~~ perm_names_types, length new_type_names)))
- (map (fn s => (Binding.name s, NONE, NoSyn)) perm_names') perm_eqs thy1;
-
- (**** prove that permutation functions introduced by unfolding are ****)
- (**** equivalent to already existing permutation functions ****)
-
- val _ = warning ("length descr: " ^ string_of_int (length descr));
- val _ = warning ("length new_type_names: " ^ string_of_int (length new_type_names));
-
- val perm_indnames = DatatypeProp.make_tnames (map body_type perm_types);
- val perm_fun_def = PureThy.get_thm thy2 "perm_fun_def";
-
- val unfolded_perm_eq_thms =
- if length descr = length new_type_names then []
- else map standard (List.drop (split_conj_thm
- (Goal.prove_global thy2 [] []
- (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
- (map (fn (c as (s, T), x) =>
- let val [T1, T2] = binder_types T
- in HOLogic.mk_eq (Const c $ pi $ Free (x, T2),
- Const ("Nominal.perm", T) $ pi $ Free (x, T2))
- end)
- (perm_names_types ~~ perm_indnames))))
- (fn _ => EVERY [indtac induction perm_indnames 1,
- ALLGOALS (asm_full_simp_tac
- (simpset_of thy2 addsimps [perm_fun_def]))])),
- length new_type_names));
-
- (**** prove [] \<bullet> t = t ****)
-
- val _ = warning "perm_empty_thms";
-
- val perm_empty_thms = List.concat (map (fn a =>
- let val permT = mk_permT (Type (a, []))
- in map standard (List.take (split_conj_thm
- (Goal.prove_global thy2 [] []
- (augment_sort thy2 [pt_class_of thy2 a]
- (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
- (map (fn ((s, T), x) => HOLogic.mk_eq
- (Const (s, permT --> T --> T) $
- Const ("List.list.Nil", permT) $ Free (x, T),
- Free (x, T)))
- (perm_names ~~
- map body_type perm_types ~~ perm_indnames)))))
- (fn _ => EVERY [indtac induction perm_indnames 1,
- ALLGOALS (asm_full_simp_tac (simpset_of thy2))])),
- length new_type_names))
- end)
- atoms);
-
- (**** prove (pi1 @ pi2) \<bullet> t = pi1 \<bullet> (pi2 \<bullet> t) ****)
-
- val _ = warning "perm_append_thms";
-
- (*FIXME: these should be looked up statically*)
- val at_pt_inst = PureThy.get_thm thy2 "at_pt_inst";
- val pt2 = PureThy.get_thm thy2 "pt2";
-
- val perm_append_thms = List.concat (map (fn a =>
- let
- val permT = mk_permT (Type (a, []));
- val pi1 = Free ("pi1", permT);
- val pi2 = Free ("pi2", permT);
- val pt_inst = pt_inst_of thy2 a;
- val pt2' = pt_inst RS pt2;
- val pt2_ax = PureThy.get_thm thy2 (Long_Name.map_base_name (fn s => "pt_" ^ s ^ "2") a);
- in List.take (map standard (split_conj_thm
- (Goal.prove_global thy2 [] []
- (augment_sort thy2 [pt_class_of thy2 a]
- (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
- (map (fn ((s, T), x) =>
- let val perm = Const (s, permT --> T --> T)
- in HOLogic.mk_eq
- (perm $ (Const ("List.append", permT --> permT --> permT) $
- pi1 $ pi2) $ Free (x, T),
- perm $ pi1 $ (perm $ pi2 $ Free (x, T)))
- end)
- (perm_names ~~
- map body_type perm_types ~~ perm_indnames)))))
- (fn _ => EVERY [indtac induction perm_indnames 1,
- ALLGOALS (asm_full_simp_tac (simpset_of thy2 addsimps [pt2', pt2_ax]))]))),
- length new_type_names)
- end) atoms);
-
- (**** prove pi1 ~ pi2 ==> pi1 \<bullet> t = pi2 \<bullet> t ****)
-
- val _ = warning "perm_eq_thms";
-
- val pt3 = PureThy.get_thm thy2 "pt3";
- val pt3_rev = PureThy.get_thm thy2 "pt3_rev";
-
- val perm_eq_thms = List.concat (map (fn a =>
- let
- val permT = mk_permT (Type (a, []));
- val pi1 = Free ("pi1", permT);
- val pi2 = Free ("pi2", permT);
- val at_inst = at_inst_of thy2 a;
- val pt_inst = pt_inst_of thy2 a;
- val pt3' = pt_inst RS pt3;
- val pt3_rev' = at_inst RS (pt_inst RS pt3_rev);
- val pt3_ax = PureThy.get_thm thy2 (Long_Name.map_base_name (fn s => "pt_" ^ s ^ "3") a);
- in List.take (map standard (split_conj_thm
- (Goal.prove_global thy2 [] []
- (augment_sort thy2 [pt_class_of thy2 a] (Logic.mk_implies
- (HOLogic.mk_Trueprop (Const ("Nominal.prm_eq",
- permT --> permT --> HOLogic.boolT) $ pi1 $ pi2),
- HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
- (map (fn ((s, T), x) =>
- let val perm = Const (s, permT --> T --> T)
- in HOLogic.mk_eq
- (perm $ pi1 $ Free (x, T),
- perm $ pi2 $ Free (x, T))
- end)
- (perm_names ~~
- map body_type perm_types ~~ perm_indnames))))))
- (fn _ => EVERY [indtac induction perm_indnames 1,
- ALLGOALS (asm_full_simp_tac (simpset_of thy2 addsimps [pt3', pt3_rev', pt3_ax]))]))),
- length new_type_names)
- end) atoms);
-
- (**** prove pi1 \<bullet> (pi2 \<bullet> t) = (pi1 \<bullet> pi2) \<bullet> (pi1 \<bullet> t) ****)
-
- val cp1 = PureThy.get_thm thy2 "cp1";
- val dj_cp = PureThy.get_thm thy2 "dj_cp";
- val pt_perm_compose = PureThy.get_thm thy2 "pt_perm_compose";
- val pt_perm_compose_rev = PureThy.get_thm thy2 "pt_perm_compose_rev";
- val dj_perm_perm_forget = PureThy.get_thm thy2 "dj_perm_perm_forget";
-
- fun composition_instance name1 name2 thy =
- let
- val cp_class = cp_class_of thy name1 name2;
- val pt_class =
- if name1 = name2 then [pt_class_of thy name1]
- else [];
- val permT1 = mk_permT (Type (name1, []));
- val permT2 = mk_permT (Type (name2, []));
- val Ts = map body_type perm_types;
- val cp_inst = cp_inst_of thy name1 name2;
- val simps = simpset_of thy addsimps (perm_fun_def ::
- (if name1 <> name2 then
- let val dj = dj_thm_of thy name2 name1
- in [dj RS (cp_inst RS dj_cp), dj RS dj_perm_perm_forget] end
- else
- let
- val at_inst = at_inst_of thy name1;
- val pt_inst = pt_inst_of thy name1;
- in
- [cp_inst RS cp1 RS sym,
- at_inst RS (pt_inst RS pt_perm_compose) RS sym,
- at_inst RS (pt_inst RS pt_perm_compose_rev) RS sym]
- end))
- val sort = Sign.certify_sort thy (cp_class :: pt_class);
- val thms = split_conj_thm (Goal.prove_global thy [] []
- (augment_sort thy sort
- (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
- (map (fn ((s, T), x) =>
- let
- val pi1 = Free ("pi1", permT1);
- val pi2 = Free ("pi2", permT2);
- val perm1 = Const (s, permT1 --> T --> T);
- val perm2 = Const (s, permT2 --> T --> T);
- val perm3 = Const ("Nominal.perm", permT1 --> permT2 --> permT2)
- in HOLogic.mk_eq
- (perm1 $ pi1 $ (perm2 $ pi2 $ Free (x, T)),
- perm2 $ (perm3 $ pi1 $ pi2) $ (perm1 $ pi1 $ Free (x, T)))
- end)
- (perm_names ~~ Ts ~~ perm_indnames)))))
- (fn _ => EVERY [indtac induction perm_indnames 1,
- ALLGOALS (asm_full_simp_tac simps)]))
- in
- fold (fn (s, tvs) => fn thy => AxClass.prove_arity
- (s, map (inter_sort thy sort o snd) tvs, [cp_class])
- (Class.intro_classes_tac [] THEN ALLGOALS (resolve_tac thms)) thy)
- (full_new_type_names' ~~ tyvars) thy
- end;
-
- val (perm_thmss,thy3) = thy2 |>
- fold (fn name1 => fold (composition_instance name1) atoms) atoms |>
- fold (fn atom => fn thy =>
- let val pt_name = pt_class_of thy atom
- in
- fold (fn (s, tvs) => fn thy => AxClass.prove_arity
- (s, map (inter_sort thy [pt_name] o snd) tvs, [pt_name])
- (EVERY
- [Class.intro_classes_tac [],
- resolve_tac perm_empty_thms 1,
- resolve_tac perm_append_thms 1,
- resolve_tac perm_eq_thms 1, assume_tac 1]) thy)
- (full_new_type_names' ~~ tyvars) thy
- end) atoms |>
- PureThy.add_thmss
- [((Binding.name (space_implode "_" new_type_names ^ "_unfolded_perm_eq"),
- unfolded_perm_eq_thms), [Simplifier.simp_add]),
- ((Binding.name (space_implode "_" new_type_names ^ "_perm_empty"),
- perm_empty_thms), [Simplifier.simp_add]),
- ((Binding.name (space_implode "_" new_type_names ^ "_perm_append"),
- perm_append_thms), [Simplifier.simp_add]),
- ((Binding.name (space_implode "_" new_type_names ^ "_perm_eq"),
- perm_eq_thms), [Simplifier.simp_add])];
-
- (**** Define representing sets ****)
-
- val _ = warning "representing sets";
-
- val rep_set_names = DatatypeProp.indexify_names
- (map (fn (i, _) => name_of_typ (nth_dtyp i) ^ "_set") descr);
- val big_rep_name =
- space_implode "_" (DatatypeProp.indexify_names (List.mapPartial
- (fn (i, ("Nominal.noption", _, _)) => NONE
- | (i, _) => SOME (name_of_typ (nth_dtyp i))) descr)) ^ "_set";
- val _ = warning ("big_rep_name: " ^ big_rep_name);
-
- fun strip_option (dtf as DtType ("fun", [dt, DtRec i])) =
- (case AList.lookup op = descr i of
- SOME ("Nominal.noption", _, [(_, [dt']), _]) =>
- apfst (cons dt) (strip_option dt')
- | _ => ([], dtf))
- | strip_option (DtType ("fun", [dt, DtType ("Nominal.noption", [dt'])])) =
- apfst (cons dt) (strip_option dt')
- | strip_option dt = ([], dt);
-
- val dt_atomTs = distinct op = (map (typ_of_dtyp descr sorts)
- (List.concat (map (fn (_, (_, _, cs)) => List.concat
- (map (List.concat o map (fst o strip_option) o snd) cs)) descr)));
- val dt_atoms = map (fst o dest_Type) dt_atomTs;
-
- fun make_intr s T (cname, cargs) =
- let
- fun mk_prem (dt, (j, j', prems, ts)) =
- let
- val (dts, dt') = strip_option dt;
- val (dts', dt'') = strip_dtyp dt';
- val Ts = map (typ_of_dtyp descr sorts) dts;
- val Us = map (typ_of_dtyp descr sorts) dts';
- val T = typ_of_dtyp descr sorts dt'';
- val free = mk_Free "x" (Us ---> T) j;
- val free' = app_bnds free (length Us);
- fun mk_abs_fun (T, (i, t)) =
- let val U = fastype_of t
- in (i + 1, Const ("Nominal.abs_fun", [T, U, T] --->
- Type ("Nominal.noption", [U])) $ mk_Free "y" T i $ t)
- end
- in (j + 1, j' + length Ts,
- case dt'' of
- DtRec k => list_all (map (pair "x") Us,
- HOLogic.mk_Trueprop (Free (List.nth (rep_set_names, k),
- T --> HOLogic.boolT) $ free')) :: prems
- | _ => prems,
- snd (List.foldr mk_abs_fun (j', free) Ts) :: ts)
- end;
-
- val (_, _, prems, ts) = List.foldr mk_prem (1, 1, [], []) cargs;
- val concl = HOLogic.mk_Trueprop (Free (s, T --> HOLogic.boolT) $
- list_comb (Const (cname, map fastype_of ts ---> T), ts))
- in Logic.list_implies (prems, concl)
- end;
-
- val (intr_ts, (rep_set_names', recTs')) =
- apfst List.concat (apsnd ListPair.unzip (ListPair.unzip (List.mapPartial
- (fn ((_, ("Nominal.noption", _, _)), _) => NONE
- | ((i, (_, _, constrs)), rep_set_name) =>
- let val T = nth_dtyp i
- in SOME (map (make_intr rep_set_name T) constrs,
- (rep_set_name, T))
- end)
- (descr ~~ rep_set_names))));
- val rep_set_names'' = map (Sign.full_bname thy3) rep_set_names';
-
- val ({raw_induct = rep_induct, intrs = rep_intrs, ...}, thy4) =
- InductivePackage.add_inductive_global (serial_string ())
- {quiet_mode = false, verbose = false, kind = Thm.internalK,
- alt_name = Binding.name big_rep_name, coind = false, no_elim = true, no_ind = false,
- skip_mono = true, fork_mono = false}
- (map (fn (s, T) => ((Binding.name s, T --> HOLogic.boolT), NoSyn))
- (rep_set_names' ~~ recTs'))
- [] (map (fn x => (Attrib.empty_binding, x)) intr_ts) [] thy3;
-
- (**** Prove that representing set is closed under permutation ****)
-
- val _ = warning "proving closure under permutation...";
-
- val abs_perm = PureThy.get_thms thy4 "abs_perm";
-
- val perm_indnames' = List.mapPartial
- (fn (x, (_, ("Nominal.noption", _, _))) => NONE | (x, _) => SOME x)
- (perm_indnames ~~ descr);
-
- fun mk_perm_closed name = map (fn th => standard (th RS mp))
- (List.take (split_conj_thm (Goal.prove_global thy4 [] []
- (augment_sort thy4
- (pt_class_of thy4 name :: map (cp_class_of thy4 name) (dt_atoms \ name))
- (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj (map
- (fn ((s, T), x) =>
- let
- val S = Const (s, T --> HOLogic.boolT);
- val permT = mk_permT (Type (name, []))
- in HOLogic.mk_imp (S $ Free (x, T),
- S $ (Const ("Nominal.perm", permT --> T --> T) $
- Free ("pi", permT) $ Free (x, T)))
- end) (rep_set_names'' ~~ recTs' ~~ perm_indnames')))))
- (fn _ => EVERY
- [indtac rep_induct [] 1,
- ALLGOALS (simp_tac (simpset_of thy4 addsimps
- (symmetric perm_fun_def :: abs_perm))),
- ALLGOALS (resolve_tac rep_intrs THEN_ALL_NEW assume_tac)])),
- length new_type_names));
-
- val perm_closed_thmss = map mk_perm_closed atoms;
-
- (**** typedef ****)
-
- val _ = warning "defining type...";
-
- val (typedefs, thy6) =
- thy4
- |> fold_map (fn ((((name, mx), tvs), (cname, U)), name') => fn thy =>
- TypedefPackage.add_typedef false (SOME (Binding.name name'))
- (Binding.name name, map fst tvs, mx)
- (Const ("Collect", (U --> HOLogic.boolT) --> HOLogic.mk_setT U) $
- Const (cname, U --> HOLogic.boolT)) NONE
- (rtac exI 1 THEN rtac CollectI 1 THEN
- QUIET_BREADTH_FIRST (has_fewer_prems 1)
- (resolve_tac rep_intrs 1)) thy |> (fn ((_, r), thy) =>
- let
- val permT = mk_permT
- (TFree (Name.variant (map fst tvs) "'a", HOLogic.typeS));
- val pi = Free ("pi", permT);
- val T = Type (Sign.intern_type thy name, map TFree tvs);
- in apfst (pair r o hd)
- (PureThy.add_defs_unchecked true [((Binding.name ("prm_" ^ name ^ "_def"), Logic.mk_equals
- (Const ("Nominal.perm", permT --> T --> T) $ pi $ Free ("x", T),
- Const (Sign.intern_const thy ("Abs_" ^ name), U --> T) $
- (Const ("Nominal.perm", permT --> U --> U) $ pi $
- (Const (Sign.intern_const thy ("Rep_" ^ name), T --> U) $
- Free ("x", T))))), [])] thy)
- end))
- (types_syntax ~~ tyvars ~~
- List.take (rep_set_names'' ~~ recTs', length new_type_names) ~~
- new_type_names);
-
- val perm_defs = map snd typedefs;
- val Abs_inverse_thms = map (collect_simp o #Abs_inverse o fst) typedefs;
- val Rep_inverse_thms = map (#Rep_inverse o fst) typedefs;
- val Rep_thms = map (collect_simp o #Rep o fst) typedefs;
-
-
- (** prove that new types are in class pt_<name> **)
-
- val _ = warning "prove that new types are in class pt_<name> ...";
-
- fun pt_instance (atom, perm_closed_thms) =
- fold (fn ((((((Abs_inverse, Rep_inverse), Rep),
- perm_def), name), tvs), perm_closed) => fn thy =>
- let
- val pt_class = pt_class_of thy atom;
- val sort = Sign.certify_sort thy
- (pt_class :: map (cp_class_of thy atom) (dt_atoms \ atom))
- in AxClass.prove_arity
- (Sign.intern_type thy name,
- map (inter_sort thy sort o snd) tvs, [pt_class])
- (EVERY [Class.intro_classes_tac [],
- rewrite_goals_tac [perm_def],
- asm_full_simp_tac (simpset_of thy addsimps [Rep_inverse]) 1,
- asm_full_simp_tac (simpset_of thy addsimps
- [Rep RS perm_closed RS Abs_inverse]) 1,
- asm_full_simp_tac (HOL_basic_ss addsimps [PureThy.get_thm thy
- ("pt_" ^ Long_Name.base_name atom ^ "3")]) 1]) thy
- end)
- (Abs_inverse_thms ~~ Rep_inverse_thms ~~ Rep_thms ~~ perm_defs ~~
- new_type_names ~~ tyvars ~~ perm_closed_thms);
-
-
- (** prove that new types are in class cp_<name1>_<name2> **)
-
- val _ = warning "prove that new types are in class cp_<name1>_<name2> ...";
-
- fun cp_instance (atom1, perm_closed_thms1) (atom2, perm_closed_thms2) thy =
- let
- val cp_class = cp_class_of thy atom1 atom2;
- val sort = Sign.certify_sort thy
- (pt_class_of thy atom1 :: map (cp_class_of thy atom1) (dt_atoms \ atom1) @
- (if atom1 = atom2 then [cp_class_of thy atom1 atom1] else
- pt_class_of thy atom2 :: map (cp_class_of thy atom2) (dt_atoms \ atom2)));
- val cp1' = cp_inst_of thy atom1 atom2 RS cp1
- in fold (fn ((((((Abs_inverse, Rep),
- perm_def), name), tvs), perm_closed1), perm_closed2) => fn thy =>
- AxClass.prove_arity
- (Sign.intern_type thy name,
- map (inter_sort thy sort o snd) tvs, [cp_class])
- (EVERY [Class.intro_classes_tac [],
- rewrite_goals_tac [perm_def],
- asm_full_simp_tac (simpset_of thy addsimps
- ((Rep RS perm_closed1 RS Abs_inverse) ::
- (if atom1 = atom2 then []
- else [Rep RS perm_closed2 RS Abs_inverse]))) 1,
- cong_tac 1,
- rtac refl 1,
- rtac cp1' 1]) thy)
- (Abs_inverse_thms ~~ Rep_thms ~~ perm_defs ~~ new_type_names ~~
- tyvars ~~ perm_closed_thms1 ~~ perm_closed_thms2) thy
- end;
-
- val thy7 = fold (fn x => fn thy => thy |>
- pt_instance x |>
- fold (cp_instance x) (atoms ~~ perm_closed_thmss))
- (atoms ~~ perm_closed_thmss) thy6;
-
- (**** constructors ****)
-
- fun mk_abs_fun (x, t) =
- let
- val T = fastype_of x;
- val U = fastype_of t
- in
- Const ("Nominal.abs_fun", T --> U --> T -->
- Type ("Nominal.noption", [U])) $ x $ t
- end;
-
- val (ty_idxs, _) = List.foldl
- (fn ((i, ("Nominal.noption", _, _)), p) => p
- | ((i, _), (ty_idxs, j)) => (ty_idxs @ [(i, j)], j + 1)) ([], 0) descr;
-
- fun reindex (DtType (s, dts)) = DtType (s, map reindex dts)
- | reindex (DtRec i) = DtRec (the (AList.lookup op = ty_idxs i))
- | reindex dt = dt;
-
- fun strip_suffix i s = implode (List.take (explode s, size s - i));
-
- (** strips the "_Rep" in type names *)
- fun strip_nth_name i s =
- let val xs = Long_Name.explode s;
- in Long_Name.implode (Library.nth_map (length xs - i) (strip_suffix 4) xs) end;
-
- val (descr'', ndescr) = ListPair.unzip (map_filter
- (fn (i, ("Nominal.noption", _, _)) => NONE
- | (i, (s, dts, constrs)) =>
- let
- val SOME index = AList.lookup op = ty_idxs i;
- val (constrs2, constrs1) =
- map_split (fn (cname, cargs) =>
- apsnd (pair (strip_nth_name 2 (strip_nth_name 1 cname)))
- (fold_map (fn dt => fn dts =>
- let val (dts', dt') = strip_option dt
- in ((length dts, length dts'), dts @ dts' @ [reindex dt']) end)
- cargs [])) constrs
- in SOME ((index, (strip_nth_name 1 s, map reindex dts, constrs1)),
- (index, constrs2))
- end) descr);
-
- val (descr1, descr2) = chop (length new_type_names) descr'';
- val descr' = [descr1, descr2];
-
- fun partition_cargs idxs xs = map (fn (i, j) =>
- (List.take (List.drop (xs, i), j), List.nth (xs, i + j))) idxs;
-
- val pdescr = map (fn ((i, (s, dts, constrs)), (_, idxss)) => (i, (s, dts,
- map (fn ((cname, cargs), idxs) => (cname, partition_cargs idxs cargs))
- (constrs ~~ idxss)))) (descr'' ~~ ndescr);
-
- fun nth_dtyp' i = typ_of_dtyp descr'' sorts (DtRec i);
-
- val rep_names = map (fn s =>
- Sign.intern_const thy7 ("Rep_" ^ s)) new_type_names;
- val abs_names = map (fn s =>
- Sign.intern_const thy7 ("Abs_" ^ s)) new_type_names;
-
- val recTs = get_rec_types descr'' sorts;
- val newTs' = Library.take (length new_type_names, recTs');
- val newTs = Library.take (length new_type_names, recTs);
-
- val full_new_type_names = map (Sign.full_bname thy) new_type_names;
-
- fun make_constr_def tname T T' ((thy, defs, eqns),
- (((cname_rep, _), (cname, cargs)), (cname', mx))) =
- let
- fun constr_arg ((dts, dt), (j, l_args, r_args)) =
- let
- val xs = map (fn (dt, i) => mk_Free "x" (typ_of_dtyp descr'' sorts dt) i)
- (dts ~~ (j upto j + length dts - 1))
- val x = mk_Free "x" (typ_of_dtyp descr'' sorts dt) (j + length dts)
- in
- (j + length dts + 1,
- xs @ x :: l_args,
- List.foldr mk_abs_fun
- (case dt of
- DtRec k => if k < length new_type_names then
- Const (List.nth (rep_names, k), typ_of_dtyp descr'' sorts dt -->
- typ_of_dtyp descr sorts dt) $ x
- else error "nested recursion not (yet) supported"
- | _ => x) xs :: r_args)
- end
-
- val (_, l_args, r_args) = List.foldr constr_arg (1, [], []) cargs;
- val abs_name = Sign.intern_const thy ("Abs_" ^ tname);
- val rep_name = Sign.intern_const thy ("Rep_" ^ tname);
- val constrT = map fastype_of l_args ---> T;
- val lhs = list_comb (Const (cname, constrT), l_args);
- val rhs = list_comb (Const (cname_rep, map fastype_of r_args ---> T'), r_args);
- val def = Logic.mk_equals (lhs, Const (abs_name, T' --> T) $ rhs);
- val eqn = HOLogic.mk_Trueprop (HOLogic.mk_eq
- (Const (rep_name, T --> T') $ lhs, rhs));
- val def_name = (Long_Name.base_name cname) ^ "_def";
- val ([def_thm], thy') = thy |>
- Sign.add_consts_i [(Binding.name cname', constrT, mx)] |>
- (PureThy.add_defs false o map Thm.no_attributes) [(Binding.name def_name, def)]
- in (thy', defs @ [def_thm], eqns @ [eqn]) end;
-
- fun dt_constr_defs ((thy, defs, eqns, dist_lemmas), ((((((_, (_, _, constrs)),
- (_, (_, _, constrs'))), tname), T), T'), constr_syntax)) =
- let
- val rep_const = cterm_of thy
- (Const (Sign.intern_const thy ("Rep_" ^ tname), T --> T'));
- val dist = standard (cterm_instantiate [(cterm_of thy distinct_f, rep_const)] distinct_lemma);
- val (thy', defs', eqns') = Library.foldl (make_constr_def tname T T')
- ((Sign.add_path tname thy, defs, []), constrs ~~ constrs' ~~ constr_syntax)
- in
- (parent_path (#flat_names config) thy', defs', eqns @ [eqns'], dist_lemmas @ [dist])
- end;
-
- val (thy8, constr_defs, constr_rep_eqns, dist_lemmas) = Library.foldl dt_constr_defs
- ((thy7, [], [], []), List.take (descr, length new_type_names) ~~
- List.take (pdescr, length new_type_names) ~~
- new_type_names ~~ newTs ~~ newTs' ~~ constr_syntax);
-
- val abs_inject_thms = map (collect_simp o #Abs_inject o fst) typedefs
- val rep_inject_thms = map (#Rep_inject o fst) typedefs
-
- (* prove theorem Rep_i (Constr_j ...) = Constr'_j ... *)
-
- fun prove_constr_rep_thm eqn =
- let
- val inj_thms = map (fn r => r RS iffD1) abs_inject_thms;
- val rewrites = constr_defs @ map mk_meta_eq Rep_inverse_thms
- in Goal.prove_global thy8 [] [] eqn (fn _ => EVERY
- [resolve_tac inj_thms 1,
- rewrite_goals_tac rewrites,
- rtac refl 3,
- resolve_tac rep_intrs 2,
- REPEAT (resolve_tac Rep_thms 1)])
- end;
-
- val constr_rep_thmss = map (map prove_constr_rep_thm) constr_rep_eqns;
-
- (* prove theorem pi \<bullet> Rep_i x = Rep_i (pi \<bullet> x) *)
-
- fun prove_perm_rep_perm (atom, perm_closed_thms) = map (fn th =>
- let
- val _ $ (_ $ (Rep $ x)) = Logic.unvarify (prop_of th);
- val Type ("fun", [T, U]) = fastype_of Rep;
- val permT = mk_permT (Type (atom, []));
- val pi = Free ("pi", permT);
- in
- Goal.prove_global thy8 [] []
- (augment_sort thy8
- (pt_class_of thy8 atom :: map (cp_class_of thy8 atom) (dt_atoms \ atom))
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (Const ("Nominal.perm", permT --> U --> U) $ pi $ (Rep $ x),
- Rep $ (Const ("Nominal.perm", permT --> T --> T) $ pi $ x)))))
- (fn _ => simp_tac (HOL_basic_ss addsimps (perm_defs @ Abs_inverse_thms @
- perm_closed_thms @ Rep_thms)) 1)
- end) Rep_thms;
-
- val perm_rep_perm_thms = List.concat (map prove_perm_rep_perm
- (atoms ~~ perm_closed_thmss));
-
- (* prove distinctness theorems *)
-
- val distinct_props = DatatypeProp.make_distincts descr' sorts;
- val dist_rewrites = map2 (fn rep_thms => fn dist_lemma =>
- dist_lemma :: rep_thms @ [In0_eq, In1_eq, In0_not_In1, In1_not_In0])
- constr_rep_thmss dist_lemmas;
-
- fun prove_distinct_thms _ (_, []) = []
- | prove_distinct_thms (p as (rep_thms, dist_lemma)) (k, t :: ts) =
- let
- val dist_thm = Goal.prove_global thy8 [] [] t (fn _ =>
- simp_tac (simpset_of thy8 addsimps (dist_lemma :: rep_thms)) 1)
- in dist_thm :: standard (dist_thm RS not_sym) ::
- prove_distinct_thms p (k, ts)
- end;
-
- val distinct_thms = map2 prove_distinct_thms
- (constr_rep_thmss ~~ dist_lemmas) distinct_props;
-
- (** prove equations for permutation functions **)
-
- val perm_simps' = map (fn (((i, (_, _, constrs)), tname), constr_rep_thms) =>
- let val T = nth_dtyp' i
- in List.concat (map (fn (atom, perm_closed_thms) =>
- map (fn ((cname, dts), constr_rep_thm) =>
- let
- val cname = Sign.intern_const thy8
- (Long_Name.append tname (Long_Name.base_name cname));
- val permT = mk_permT (Type (atom, []));
- val pi = Free ("pi", permT);
-
- fun perm t =
- let val T = fastype_of t
- in Const ("Nominal.perm", permT --> T --> T) $ pi $ t end;
-
- fun constr_arg ((dts, dt), (j, l_args, r_args)) =
- let
- val Ts = map (typ_of_dtyp descr'' sorts) dts;
- val xs = map (fn (T, i) => mk_Free "x" T i)
- (Ts ~~ (j upto j + length dts - 1))
- val x = mk_Free "x" (typ_of_dtyp descr'' sorts dt) (j + length dts)
- in
- (j + length dts + 1,
- xs @ x :: l_args,
- map perm (xs @ [x]) @ r_args)
- end
-
- val (_, l_args, r_args) = List.foldr constr_arg (1, [], []) dts;
- val c = Const (cname, map fastype_of l_args ---> T)
- in
- Goal.prove_global thy8 [] []
- (augment_sort thy8
- (pt_class_of thy8 atom :: map (cp_class_of thy8 atom) (dt_atoms \ atom))
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (perm (list_comb (c, l_args)), list_comb (c, r_args)))))
- (fn _ => EVERY
- [simp_tac (simpset_of thy8 addsimps (constr_rep_thm :: perm_defs)) 1,
- simp_tac (HOL_basic_ss addsimps (Rep_thms @ Abs_inverse_thms @
- constr_defs @ perm_closed_thms)) 1,
- TRY (simp_tac (HOL_basic_ss addsimps
- (symmetric perm_fun_def :: abs_perm)) 1),
- TRY (simp_tac (HOL_basic_ss addsimps
- (perm_fun_def :: perm_defs @ Rep_thms @ Abs_inverse_thms @
- perm_closed_thms)) 1)])
- end) (constrs ~~ constr_rep_thms)) (atoms ~~ perm_closed_thmss))
- end) (List.take (pdescr, length new_type_names) ~~ new_type_names ~~ constr_rep_thmss);
-
- (** prove injectivity of constructors **)
-
- val rep_inject_thms' = map (fn th => th RS sym) rep_inject_thms;
- val alpha = PureThy.get_thms thy8 "alpha";
- val abs_fresh = PureThy.get_thms thy8 "abs_fresh";
-
- val pt_cp_sort =
- map (pt_class_of thy8) dt_atoms @
- maps (fn s => map (cp_class_of thy8 s) (dt_atoms \ s)) dt_atoms;
-
- val inject_thms = map (fn (((i, (_, _, constrs)), tname), constr_rep_thms) =>
- let val T = nth_dtyp' i
- in List.mapPartial (fn ((cname, dts), constr_rep_thm) =>
- if null dts then NONE else SOME
- let
- val cname = Sign.intern_const thy8
- (Long_Name.append tname (Long_Name.base_name cname));
-
- fun make_inj ((dts, dt), (j, args1, args2, eqs)) =
- let
- val Ts_idx = map (typ_of_dtyp descr'' sorts) dts ~~ (j upto j + length dts - 1);
- val xs = map (fn (T, i) => mk_Free "x" T i) Ts_idx;
- val ys = map (fn (T, i) => mk_Free "y" T i) Ts_idx;
- val x = mk_Free "x" (typ_of_dtyp descr'' sorts dt) (j + length dts);
- val y = mk_Free "y" (typ_of_dtyp descr'' sorts dt) (j + length dts)
- in
- (j + length dts + 1,
- xs @ (x :: args1), ys @ (y :: args2),
- HOLogic.mk_eq
- (List.foldr mk_abs_fun x xs, List.foldr mk_abs_fun y ys) :: eqs)
- end;
-
- val (_, args1, args2, eqs) = List.foldr make_inj (1, [], [], []) dts;
- val Ts = map fastype_of args1;
- val c = Const (cname, Ts ---> T)
- in
- Goal.prove_global thy8 [] []
- (augment_sort thy8 pt_cp_sort
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (HOLogic.mk_eq (list_comb (c, args1), list_comb (c, args2)),
- foldr1 HOLogic.mk_conj eqs))))
- (fn _ => EVERY
- [asm_full_simp_tac (simpset_of thy8 addsimps (constr_rep_thm ::
- rep_inject_thms')) 1,
- TRY (asm_full_simp_tac (HOL_basic_ss addsimps (fresh_def :: supp_def ::
- alpha @ abs_perm @ abs_fresh @ rep_inject_thms @
- perm_rep_perm_thms)) 1)])
- end) (constrs ~~ constr_rep_thms)
- end) (List.take (pdescr, length new_type_names) ~~ new_type_names ~~ constr_rep_thmss);
-
- (** equations for support and freshness **)
-
- val (supp_thms, fresh_thms) = ListPair.unzip (map ListPair.unzip
- (map (fn ((((i, (_, _, constrs)), tname), inject_thms'), perm_thms') =>
- let val T = nth_dtyp' i
- in List.concat (map (fn (cname, dts) => map (fn atom =>
- let
- val cname = Sign.intern_const thy8
- (Long_Name.append tname (Long_Name.base_name cname));
- val atomT = Type (atom, []);
-
- fun process_constr ((dts, dt), (j, args1, args2)) =
- let
- val Ts_idx = map (typ_of_dtyp descr'' sorts) dts ~~ (j upto j + length dts - 1);
- val xs = map (fn (T, i) => mk_Free "x" T i) Ts_idx;
- val x = mk_Free "x" (typ_of_dtyp descr'' sorts dt) (j + length dts)
- in
- (j + length dts + 1,
- xs @ (x :: args1), List.foldr mk_abs_fun x xs :: args2)
- end;
-
- val (_, args1, args2) = List.foldr process_constr (1, [], []) dts;
- val Ts = map fastype_of args1;
- val c = list_comb (Const (cname, Ts ---> T), args1);
- fun supp t =
- Const ("Nominal.supp", fastype_of t --> HOLogic.mk_setT atomT) $ t;
- fun fresh t = fresh_const atomT (fastype_of t) $ Free ("a", atomT) $ t;
- val supp_thm = Goal.prove_global thy8 [] []
- (augment_sort thy8 pt_cp_sort
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (supp c,
- if null dts then HOLogic.mk_set atomT []
- else foldr1 (HOLogic.mk_binop @{const_name Un}) (map supp args2)))))
- (fn _ =>
- simp_tac (HOL_basic_ss addsimps (supp_def ::
- Un_assoc :: de_Morgan_conj :: Collect_disj_eq :: finite_Un ::
- symmetric empty_def :: finite_emptyI :: simp_thms @
- abs_perm @ abs_fresh @ inject_thms' @ perm_thms')) 1)
- in
- (supp_thm,
- Goal.prove_global thy8 [] [] (augment_sort thy8 pt_cp_sort
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (fresh c,
- if null dts then HOLogic.true_const
- else foldr1 HOLogic.mk_conj (map fresh args2)))))
- (fn _ =>
- simp_tac (HOL_ss addsimps [Un_iff, empty_iff, fresh_def, supp_thm]) 1))
- end) atoms) constrs)
- end) (List.take (pdescr, length new_type_names) ~~ new_type_names ~~ inject_thms ~~ perm_simps')));
-
- (**** weak induction theorem ****)
-
- fun mk_indrule_lemma ((prems, concls), (((i, _), T), U)) =
- let
- val Rep_t = Const (List.nth (rep_names, i), T --> U) $
- mk_Free "x" T i;
-
- val Abs_t = Const (List.nth (abs_names, i), U --> T)
-
- in (prems @ [HOLogic.imp $
- (Const (List.nth (rep_set_names'', i), U --> HOLogic.boolT) $ Rep_t) $
- (mk_Free "P" (T --> HOLogic.boolT) (i + 1) $ (Abs_t $ Rep_t))],
- concls @ [mk_Free "P" (T --> HOLogic.boolT) (i + 1) $ mk_Free "x" T i])
- end;
-
- val (indrule_lemma_prems, indrule_lemma_concls) =
- Library.foldl mk_indrule_lemma (([], []), (descr'' ~~ recTs ~~ recTs'));
-
- val indrule_lemma = Goal.prove_global thy8 [] []
- (Logic.mk_implies
- (HOLogic.mk_Trueprop (mk_conj indrule_lemma_prems),
- HOLogic.mk_Trueprop (mk_conj indrule_lemma_concls))) (fn _ => EVERY
- [REPEAT (etac conjE 1),
- REPEAT (EVERY
- [TRY (rtac conjI 1), full_simp_tac (HOL_basic_ss addsimps Rep_inverse_thms) 1,
- etac mp 1, resolve_tac Rep_thms 1])]);
-
- val Ps = map head_of (HOLogic.dest_conj (HOLogic.dest_Trueprop (concl_of indrule_lemma)));
- val frees = if length Ps = 1 then [Free ("P", snd (dest_Var (hd Ps)))] else
- map (Free o apfst fst o dest_Var) Ps;
- val indrule_lemma' = cterm_instantiate
- (map (cterm_of thy8) Ps ~~ map (cterm_of thy8) frees) indrule_lemma;
-
- val Abs_inverse_thms' = map (fn r => r RS subst) Abs_inverse_thms;
-
- val dt_induct_prop = DatatypeProp.make_ind descr' sorts;
- val dt_induct = Goal.prove_global thy8 []
- (Logic.strip_imp_prems dt_induct_prop) (Logic.strip_imp_concl dt_induct_prop)
- (fn {prems, ...} => EVERY
- [rtac indrule_lemma' 1,
- (indtac rep_induct [] THEN_ALL_NEW ObjectLogic.atomize_prems_tac) 1,
- EVERY (map (fn (prem, r) => (EVERY
- [REPEAT (eresolve_tac Abs_inverse_thms' 1),
- simp_tac (HOL_basic_ss addsimps [symmetric r]) 1,
- DEPTH_SOLVE_1 (ares_tac [prem] 1 ORELSE etac allE 1)]))
- (prems ~~ constr_defs))]);
-
- val case_names_induct = mk_case_names_induct descr'';
-
- (**** prove that new datatypes have finite support ****)
-
- val _ = warning "proving finite support for the new datatype";
-
- val indnames = DatatypeProp.make_tnames recTs;
-
- val abs_supp = PureThy.get_thms thy8 "abs_supp";
- val supp_atm = PureThy.get_thms thy8 "supp_atm";
-
- val finite_supp_thms = map (fn atom =>
- let val atomT = Type (atom, [])
- in map standard (List.take
- (split_conj_thm (Goal.prove_global thy8 [] []
- (augment_sort thy8 (fs_class_of thy8 atom :: pt_cp_sort)
- (HOLogic.mk_Trueprop
- (foldr1 HOLogic.mk_conj (map (fn (s, T) =>
- Const ("Finite_Set.finite", HOLogic.mk_setT atomT --> HOLogic.boolT) $
- (Const ("Nominal.supp", T --> HOLogic.mk_setT atomT) $ Free (s, T)))
- (indnames ~~ recTs)))))
- (fn _ => indtac dt_induct indnames 1 THEN
- ALLGOALS (asm_full_simp_tac (simpset_of thy8 addsimps
- (abs_supp @ supp_atm @
- PureThy.get_thms thy8 ("fs_" ^ Long_Name.base_name atom ^ "1") @
- List.concat supp_thms))))),
- length new_type_names))
- end) atoms;
-
- val simp_atts = replicate (length new_type_names) [Simplifier.simp_add];
-
- (* Function to add both the simp and eqvt attributes *)
- (* These two attributes are duplicated on all the types in the mutual nominal datatypes *)
-
- val simp_eqvt_atts = replicate (length new_type_names) [Simplifier.simp_add, NominalThmDecls.eqvt_add];
-
- val (_, thy9) = thy8 |>
- Sign.add_path big_name |>
- PureThy.add_thms [((Binding.name "induct", dt_induct), [case_names_induct])] ||>>
- PureThy.add_thmss [((Binding.name "inducts", projections dt_induct), [case_names_induct])] ||>
- Sign.parent_path ||>>
- DatatypeAux.store_thmss_atts "distinct" new_type_names simp_atts distinct_thms ||>>
- DatatypeAux.store_thmss "constr_rep" new_type_names constr_rep_thmss ||>>
- DatatypeAux.store_thmss_atts "perm" new_type_names simp_eqvt_atts perm_simps' ||>>
- DatatypeAux.store_thmss "inject" new_type_names inject_thms ||>>
- DatatypeAux.store_thmss "supp" new_type_names supp_thms ||>>
- DatatypeAux.store_thmss_atts "fresh" new_type_names simp_atts fresh_thms ||>
- fold (fn (atom, ths) => fn thy =>
- let
- val class = fs_class_of thy atom;
- val sort = Sign.certify_sort thy (class :: pt_cp_sort)
- in fold (fn Type (s, Ts) => AxClass.prove_arity
- (s, map (inter_sort thy sort o snd o dest_TFree) Ts, [class])
- (Class.intro_classes_tac [] THEN resolve_tac ths 1)) newTs thy
- end) (atoms ~~ finite_supp_thms);
-
- (**** strong induction theorem ****)
-
- val pnames = if length descr'' = 1 then ["P"]
- else map (fn i => "P" ^ string_of_int i) (1 upto length descr'');
- val ind_sort = if null dt_atomTs then HOLogic.typeS
- else Sign.certify_sort thy9 (map (fs_class_of thy9) dt_atoms);
- val fsT = TFree ("'n", ind_sort);
- val fsT' = TFree ("'n", HOLogic.typeS);
-
- val fresh_fs = map (fn (s, T) => (T, Free (s, fsT' --> HOLogic.mk_setT T)))
- (DatatypeProp.indexify_names (replicate (length dt_atomTs) "f") ~~ dt_atomTs);
-
- fun make_pred fsT i T =
- Free (List.nth (pnames, i), fsT --> T --> HOLogic.boolT);
-
- fun mk_fresh1 xs [] = []
- | mk_fresh1 xs ((y as (_, T)) :: ys) = map (fn x => HOLogic.mk_Trueprop
- (HOLogic.mk_not (HOLogic.mk_eq (Free y, Free x))))
- (filter (fn (_, U) => T = U) (rev xs)) @
- mk_fresh1 (y :: xs) ys;
-
- fun mk_fresh2 xss [] = []
- | mk_fresh2 xss ((p as (ys, _)) :: yss) = List.concat (map (fn y as (_, T) =>
- map (fn (_, x as (_, U)) => HOLogic.mk_Trueprop
- (fresh_const T U $ Free y $ Free x)) (rev xss @ yss)) ys) @
- mk_fresh2 (p :: xss) yss;
-
- fun make_ind_prem fsT f k T ((cname, cargs), idxs) =
- let
- val recs = List.filter is_rec_type cargs;
- val Ts = map (typ_of_dtyp descr'' sorts) cargs;
- val recTs' = map (typ_of_dtyp descr'' sorts) recs;
- val tnames = Name.variant_list pnames (DatatypeProp.make_tnames Ts);
- val rec_tnames = map fst (List.filter (is_rec_type o snd) (tnames ~~ cargs));
- val frees = tnames ~~ Ts;
- val frees' = partition_cargs idxs frees;
- val z = (Name.variant tnames "z", fsT);
-
- fun mk_prem ((dt, s), T) =
- let
- val (Us, U) = strip_type T;
- val l = length Us
- in list_all (z :: map (pair "x") Us, HOLogic.mk_Trueprop
- (make_pred fsT (body_index dt) U $ Bound l $ app_bnds (Free (s, T)) l))
- end;
-
- val prems = map mk_prem (recs ~~ rec_tnames ~~ recTs');
- val prems' = map (fn p as (_, T) => HOLogic.mk_Trueprop
- (f T (Free p) (Free z))) (List.concat (map fst frees')) @
- mk_fresh1 [] (List.concat (map fst frees')) @
- mk_fresh2 [] frees'
-
- in list_all_free (frees @ [z], Logic.list_implies (prems' @ prems,
- HOLogic.mk_Trueprop (make_pred fsT k T $ Free z $
- list_comb (Const (cname, Ts ---> T), map Free frees))))
- end;
-
- val ind_prems = List.concat (map (fn (((i, (_, _, constrs)), (_, idxss)), T) =>
- map (make_ind_prem fsT (fn T => fn t => fn u =>
- fresh_const T fsT $ t $ u) i T)
- (constrs ~~ idxss)) (descr'' ~~ ndescr ~~ recTs));
- val tnames = DatatypeProp.make_tnames recTs;
- val zs = Name.variant_list tnames (replicate (length descr'') "z");
- val ind_concl = HOLogic.mk_Trueprop (foldr1 (HOLogic.mk_binop "op &")
- (map (fn ((((i, _), T), tname), z) =>
- make_pred fsT i T $ Free (z, fsT) $ Free (tname, T))
- (descr'' ~~ recTs ~~ tnames ~~ zs)));
- val induct = Logic.list_implies (ind_prems, ind_concl);
-
- val ind_prems' =
- map (fn (_, f as Free (_, T)) => list_all_free ([("x", fsT')],
- HOLogic.mk_Trueprop (Const ("Finite_Set.finite",
- (snd (split_last (binder_types T)) --> HOLogic.boolT) -->
- HOLogic.boolT) $ (f $ Free ("x", fsT'))))) fresh_fs @
- List.concat (map (fn (((i, (_, _, constrs)), (_, idxss)), T) =>
- map (make_ind_prem fsT' (fn T => fn t => fn u => HOLogic.Not $
- HOLogic.mk_mem (t, the (AList.lookup op = fresh_fs T) $ u)) i T)
- (constrs ~~ idxss)) (descr'' ~~ ndescr ~~ recTs));
- val ind_concl' = HOLogic.mk_Trueprop (foldr1 (HOLogic.mk_binop "op &")
- (map (fn ((((i, _), T), tname), z) =>
- make_pred fsT' i T $ Free (z, fsT') $ Free (tname, T))
- (descr'' ~~ recTs ~~ tnames ~~ zs)));
- val induct' = Logic.list_implies (ind_prems', ind_concl');
-
- val aux_ind_vars =
- (DatatypeProp.indexify_names (replicate (length dt_atomTs) "pi") ~~
- map mk_permT dt_atomTs) @ [("z", fsT')];
- val aux_ind_Ts = rev (map snd aux_ind_vars);
- val aux_ind_concl = HOLogic.mk_Trueprop (foldr1 (HOLogic.mk_binop "op &")
- (map (fn (((i, _), T), tname) =>
- HOLogic.list_all (aux_ind_vars, make_pred fsT' i T $ Bound 0 $
- fold_rev (mk_perm aux_ind_Ts) (map Bound (length dt_atomTs downto 1))
- (Free (tname, T))))
- (descr'' ~~ recTs ~~ tnames)));
-
- val fin_set_supp = map (fn s =>
- at_inst_of thy9 s RS at_fin_set_supp) dt_atoms;
- val fin_set_fresh = map (fn s =>
- at_inst_of thy9 s RS at_fin_set_fresh) dt_atoms;
- val pt1_atoms = map (fn Type (s, _) =>
- PureThy.get_thm thy9 ("pt_" ^ Long_Name.base_name s ^ "1")) dt_atomTs;
- val pt2_atoms = map (fn Type (s, _) =>
- PureThy.get_thm thy9 ("pt_" ^ Long_Name.base_name s ^ "2") RS sym) dt_atomTs;
- val exists_fresh' = PureThy.get_thms thy9 "exists_fresh'";
- val fs_atoms = PureThy.get_thms thy9 "fin_supp";
- val abs_supp = PureThy.get_thms thy9 "abs_supp";
- val perm_fresh_fresh = PureThy.get_thms thy9 "perm_fresh_fresh";
- val calc_atm = PureThy.get_thms thy9 "calc_atm";
- val fresh_atm = PureThy.get_thms thy9 "fresh_atm";
- val fresh_left = PureThy.get_thms thy9 "fresh_left";
- val perm_swap = PureThy.get_thms thy9 "perm_swap";
-
- fun obtain_fresh_name' ths ts T (freshs1, freshs2, ctxt) =
- let
- val p = foldr1 HOLogic.mk_prod (ts @ freshs1);
- val ex = Goal.prove ctxt [] [] (HOLogic.mk_Trueprop
- (HOLogic.exists_const T $ Abs ("x", T,
- fresh_const T (fastype_of p) $
- Bound 0 $ p)))
- (fn _ => EVERY
- [resolve_tac exists_fresh' 1,
- simp_tac (HOL_ss addsimps (supp_prod :: finite_Un :: fs_atoms @
- fin_set_supp @ ths)) 1]);
- val (([cx], ths), ctxt') = Obtain.result
- (fn _ => EVERY
- [etac exE 1,
- full_simp_tac (HOL_ss addsimps (fresh_prod :: fresh_atm)) 1,
- REPEAT (etac conjE 1)])
- [ex] ctxt
- in (freshs1 @ [term_of cx], freshs2 @ ths, ctxt') end;
-
- fun fresh_fresh_inst thy a b =
- let
- val T = fastype_of a;
- val SOME th = find_first (fn th => case prop_of th of
- _ $ (_ $ (Const (_, Type (_, [U, _])) $ _ $ _)) $ _ => U = T
- | _ => false) perm_fresh_fresh
- in
- Drule.instantiate' []
- [SOME (cterm_of thy a), NONE, SOME (cterm_of thy b)] th
- end;
-
- val fs_cp_sort =
- map (fs_class_of thy9) dt_atoms @
- maps (fn s => map (cp_class_of thy9 s) (dt_atoms \ s)) dt_atoms;
-
- (**********************************************************************
- The subgoals occurring in the proof of induct_aux have the
- following parameters:
-
- x_1 ... x_k p_1 ... p_m z
-
- where
-
- x_i : constructor arguments (introduced by weak induction rule)
- p_i : permutations (one for each atom type in the data type)
- z : freshness context
- ***********************************************************************)
-
- val _ = warning "proving strong induction theorem ...";
-
- val induct_aux = Goal.prove_global thy9 []
- (map (augment_sort thy9 fs_cp_sort) ind_prems')
- (augment_sort thy9 fs_cp_sort ind_concl') (fn {prems, context} =>
- let
- val (prems1, prems2) = chop (length dt_atomTs) prems;
- val ind_ss2 = HOL_ss addsimps
- finite_Diff :: abs_fresh @ abs_supp @ fs_atoms;
- val ind_ss1 = ind_ss2 addsimps fresh_left @ calc_atm @
- fresh_atm @ rev_simps @ app_simps;
- val ind_ss3 = HOL_ss addsimps abs_fun_eq1 ::
- abs_perm @ calc_atm @ perm_swap;
- val ind_ss4 = HOL_basic_ss addsimps fresh_left @ prems1 @
- fin_set_fresh @ calc_atm;
- val ind_ss5 = HOL_basic_ss addsimps pt1_atoms;
- val ind_ss6 = HOL_basic_ss addsimps flat perm_simps';
- val th = Goal.prove context [] []
- (augment_sort thy9 fs_cp_sort aux_ind_concl)
- (fn {context = context1, ...} =>
- EVERY (indtac dt_induct tnames 1 ::
- maps (fn ((_, (_, _, constrs)), (_, constrs')) =>
- map (fn ((cname, cargs), is) =>
- REPEAT (rtac allI 1) THEN
- SUBPROOF (fn {prems = iprems, params, concl,
- context = context2, ...} =>
- let
- val concl' = term_of concl;
- val _ $ (_ $ _ $ u) = concl';
- val U = fastype_of u;
- val (xs, params') =
- chop (length cargs) (map term_of params);
- val Ts = map fastype_of xs;
- val cnstr = Const (cname, Ts ---> U);
- val (pis, z) = split_last params';
- val mk_pi = fold_rev (mk_perm []) pis;
- val xs' = partition_cargs is xs;
- val xs'' = map (fn (ts, u) => (map mk_pi ts, mk_pi u)) xs';
- val ts = maps (fn (ts, u) => ts @ [u]) xs'';
- val (freshs1, freshs2, context3) = fold (fn t =>
- let val T = fastype_of t
- in obtain_fresh_name' prems1
- (the (AList.lookup op = fresh_fs T) $ z :: ts) T
- end) (maps fst xs') ([], [], context2);
- val freshs1' = unflat (map fst xs') freshs1;
- val freshs2' = map (Simplifier.simplify ind_ss4)
- (mk_not_sym freshs2);
- val ind_ss1' = ind_ss1 addsimps freshs2';
- val ind_ss3' = ind_ss3 addsimps freshs2';
- val rename_eq =
- if forall (null o fst) xs' then []
- else [Goal.prove context3 [] []
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (list_comb (cnstr, ts),
- list_comb (cnstr, maps (fn ((bs, t), cs) =>
- cs @ [fold_rev (mk_perm []) (map perm_of_pair
- (bs ~~ cs)) t]) (xs'' ~~ freshs1')))))
- (fn _ => EVERY
- (simp_tac (HOL_ss addsimps flat inject_thms) 1 ::
- REPEAT (FIRSTGOAL (rtac conjI)) ::
- maps (fn ((bs, t), cs) =>
- if null bs then []
- else rtac sym 1 :: maps (fn (b, c) =>
- [rtac trans 1, rtac sym 1,
- rtac (fresh_fresh_inst thy9 b c) 1,
- simp_tac ind_ss1' 1,
- simp_tac ind_ss2 1,
- simp_tac ind_ss3' 1]) (bs ~~ cs))
- (xs'' ~~ freshs1')))];
- val th = Goal.prove context3 [] [] concl' (fn _ => EVERY
- [simp_tac (ind_ss6 addsimps rename_eq) 1,
- cut_facts_tac iprems 1,
- (resolve_tac prems THEN_ALL_NEW
- SUBGOAL (fn (t, i) => case Logic.strip_assums_concl t of
- _ $ (Const ("Nominal.fresh", _) $ _ $ _) =>
- simp_tac ind_ss1' i
- | _ $ (Const ("Not", _) $ _) =>
- resolve_tac freshs2' i
- | _ => asm_simp_tac (HOL_basic_ss addsimps
- pt2_atoms addsimprocs [perm_simproc]) i)) 1])
- val final = ProofContext.export context3 context2 [th]
- in
- resolve_tac final 1
- end) context1 1) (constrs ~~ constrs')) (descr'' ~~ ndescr)))
- in
- EVERY
- [cut_facts_tac [th] 1,
- REPEAT (eresolve_tac [conjE, @{thm allE_Nil}] 1),
- REPEAT (etac allE 1),
- REPEAT (TRY (rtac conjI 1) THEN asm_full_simp_tac ind_ss5 1)]
- end);
-
- val induct_aux' = Thm.instantiate ([],
- map (fn (s, v as Var (_, T)) =>
- (cterm_of thy9 v, cterm_of thy9 (Free (s, T))))
- (pnames ~~ map head_of (HOLogic.dest_conj
- (HOLogic.dest_Trueprop (concl_of induct_aux)))) @
- map (fn (_, f) =>
- let val f' = Logic.varify f
- in (cterm_of thy9 f',
- cterm_of thy9 (Const ("Nominal.supp", fastype_of f')))
- end) fresh_fs) induct_aux;
-
- val induct = Goal.prove_global thy9 []
- (map (augment_sort thy9 fs_cp_sort) ind_prems)
- (augment_sort thy9 fs_cp_sort ind_concl)
- (fn {prems, ...} => EVERY
- [rtac induct_aux' 1,
- REPEAT (resolve_tac fs_atoms 1),
- REPEAT ((resolve_tac prems THEN_ALL_NEW
- (etac meta_spec ORELSE' full_simp_tac (HOL_basic_ss addsimps [fresh_def]))) 1)])
-
- val (_, thy10) = thy9 |>
- Sign.add_path big_name |>
- PureThy.add_thms [((Binding.name "strong_induct'", induct_aux), [])] ||>>
- PureThy.add_thms [((Binding.name "strong_induct", induct), [case_names_induct])] ||>>
- PureThy.add_thmss [((Binding.name "strong_inducts", projections induct), [case_names_induct])];
-
- (**** recursion combinator ****)
-
- val _ = warning "defining recursion combinator ...";
-
- val used = List.foldr OldTerm.add_typ_tfree_names [] recTs;
-
- val (rec_result_Ts', rec_fn_Ts') = DatatypeProp.make_primrec_Ts descr' sorts used;
-
- val rec_sort = if null dt_atomTs then HOLogic.typeS else
- Sign.certify_sort thy10 pt_cp_sort;
-
- val rec_result_Ts = map (fn TFree (s, _) => TFree (s, rec_sort)) rec_result_Ts';
- val rec_fn_Ts = map (typ_subst_atomic (rec_result_Ts' ~~ rec_result_Ts)) rec_fn_Ts';
-
- val rec_set_Ts = map (fn (T1, T2) =>
- rec_fn_Ts @ [T1, T2] ---> HOLogic.boolT) (recTs ~~ rec_result_Ts);
-
- val big_rec_name = big_name ^ "_rec_set";
- val rec_set_names' =
- if length descr'' = 1 then [big_rec_name] else
- map ((curry (op ^) (big_rec_name ^ "_")) o string_of_int)
- (1 upto (length descr''));
- val rec_set_names = map (Sign.full_bname thy10) rec_set_names';
-
- val rec_fns = map (uncurry (mk_Free "f"))
- (rec_fn_Ts ~~ (1 upto (length rec_fn_Ts)));
- val rec_sets' = map (fn c => list_comb (Free c, rec_fns))
- (rec_set_names' ~~ rec_set_Ts);
- val rec_sets = map (fn c => list_comb (Const c, rec_fns))
- (rec_set_names ~~ rec_set_Ts);
-
- (* introduction rules for graph of recursion function *)
-
- val rec_preds = map (fn (a, T) =>
- Free (a, T --> HOLogic.boolT)) (pnames ~~ rec_result_Ts);
-
- fun mk_fresh3 rs [] = []
- | mk_fresh3 rs ((p as (ys, z)) :: yss) = List.concat (map (fn y as (_, T) =>
- List.mapPartial (fn ((_, (_, x)), r as (_, U)) => if z = x then NONE
- else SOME (HOLogic.mk_Trueprop
- (fresh_const T U $ Free y $ Free r))) rs) ys) @
- mk_fresh3 rs yss;
-
- (* FIXME: avoid collisions with other variable names? *)
- val rec_ctxt = Free ("z", fsT');
-
- fun make_rec_intr T p rec_set ((rec_intr_ts, rec_prems, rec_prems',
- rec_eq_prems, l), ((cname, cargs), idxs)) =
- let
- val Ts = map (typ_of_dtyp descr'' sorts) cargs;
- val frees = map (fn i => "x" ^ string_of_int i) (1 upto length Ts) ~~ Ts;
- val frees' = partition_cargs idxs frees;
- val binders = List.concat (map fst frees');
- val atomTs = distinct op = (maps (map snd o fst) frees');
- val recs = List.mapPartial
- (fn ((_, DtRec i), p) => SOME (i, p) | _ => NONE)
- (partition_cargs idxs cargs ~~ frees');
- val frees'' = map (fn i => "y" ^ string_of_int i) (1 upto length recs) ~~
- map (fn (i, _) => List.nth (rec_result_Ts, i)) recs;
- val prems1 = map (fn ((i, (_, x)), y) => HOLogic.mk_Trueprop
- (List.nth (rec_sets', i) $ Free x $ Free y)) (recs ~~ frees'');
- val prems2 =
- map (fn f => map (fn p as (_, T) => HOLogic.mk_Trueprop
- (fresh_const T (fastype_of f) $ Free p $ f)) binders) rec_fns;
- val prems3 = mk_fresh1 [] binders @ mk_fresh2 [] frees';
- val prems4 = map (fn ((i, _), y) =>
- HOLogic.mk_Trueprop (List.nth (rec_preds, i) $ Free y)) (recs ~~ frees'');
- val prems5 = mk_fresh3 (recs ~~ frees'') frees';
- val prems6 = maps (fn aT => map (fn y as (_, T) => HOLogic.mk_Trueprop
- (Const ("Finite_Set.finite", HOLogic.mk_setT aT --> HOLogic.boolT) $
- (Const ("Nominal.supp", T --> HOLogic.mk_setT aT) $ Free y)))
- frees'') atomTs;
- val prems7 = map (fn x as (_, T) => HOLogic.mk_Trueprop
- (fresh_const T fsT' $ Free x $ rec_ctxt)) binders;
- val result = list_comb (List.nth (rec_fns, l), map Free (frees @ frees''));
- val result_freshs = map (fn p as (_, T) =>
- fresh_const T (fastype_of result) $ Free p $ result) binders;
- val P = HOLogic.mk_Trueprop (p $ result)
- in
- (rec_intr_ts @ [Logic.list_implies (List.concat prems2 @ prems3 @ prems1,
- HOLogic.mk_Trueprop (rec_set $
- list_comb (Const (cname, Ts ---> T), map Free frees) $ result))],
- rec_prems @ [list_all_free (frees @ frees'', Logic.list_implies (prems4, P))],
- rec_prems' @ map (fn fr => list_all_free (frees @ frees'',
- Logic.list_implies (List.nth (prems2, l) @ prems3 @ prems5 @ prems7 @ prems6 @ [P],
- HOLogic.mk_Trueprop fr))) result_freshs,
- rec_eq_prems @ [List.concat prems2 @ prems3],
- l + 1)
- end;
-
- val (rec_intr_ts, rec_prems, rec_prems', rec_eq_prems, _) =
- Library.foldl (fn (x, ((((d, d'), T), p), rec_set)) =>
- Library.foldl (make_rec_intr T p rec_set) (x, #3 (snd d) ~~ snd d'))
- (([], [], [], [], 0), descr'' ~~ ndescr ~~ recTs ~~ rec_preds ~~ rec_sets');
-
- val ({intrs = rec_intrs, elims = rec_elims, raw_induct = rec_induct, ...}, thy11) =
- thy10 |>
- InductivePackage.add_inductive_global (serial_string ())
- {quiet_mode = #quiet config, verbose = false, kind = Thm.internalK,
- alt_name = Binding.name big_rec_name, coind = false, no_elim = false, no_ind = false,
- skip_mono = true, fork_mono = false}
- (map (fn (s, T) => ((Binding.name s, T), NoSyn)) (rec_set_names' ~~ rec_set_Ts))
- (map dest_Free rec_fns)
- (map (fn x => (Attrib.empty_binding, x)) rec_intr_ts) [] ||>
- PureThy.hide_fact true (Long_Name.append (Sign.full_bname thy10 big_rec_name) "induct");
-
- (** equivariance **)
-
- val fresh_bij = PureThy.get_thms thy11 "fresh_bij";
- val perm_bij = PureThy.get_thms thy11 "perm_bij";
-
- val (rec_equiv_thms, rec_equiv_thms') = ListPair.unzip (map (fn aT =>
- let
- val permT = mk_permT aT;
- val pi = Free ("pi", permT);
- val rec_fns_pi = map (mk_perm [] pi o uncurry (mk_Free "f"))
- (rec_fn_Ts ~~ (1 upto (length rec_fn_Ts)));
- val rec_sets_pi = map (fn c => list_comb (Const c, rec_fns_pi))
- (rec_set_names ~~ rec_set_Ts);
- val ps = map (fn ((((T, U), R), R'), i) =>
- let
- val x = Free ("x" ^ string_of_int i, T);
- val y = Free ("y" ^ string_of_int i, U)
- in
- (R $ x $ y, R' $ mk_perm [] pi x $ mk_perm [] pi y)
- end) (recTs ~~ rec_result_Ts ~~ rec_sets ~~ rec_sets_pi ~~ (1 upto length recTs));
- val ths = map (fn th => standard (th RS mp)) (split_conj_thm
- (Goal.prove_global thy11 [] []
- (augment_sort thy1 pt_cp_sort
- (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj (map HOLogic.mk_imp ps))))
- (fn _ => rtac rec_induct 1 THEN REPEAT
- (simp_tac (Simplifier.theory_context thy11 HOL_basic_ss
- addsimps flat perm_simps'
- addsimprocs [NominalPermeq.perm_simproc_app]) 1 THEN
- (resolve_tac rec_intrs THEN_ALL_NEW
- asm_simp_tac (HOL_ss addsimps (fresh_bij @ perm_bij))) 1))))
- val ths' = map (fn ((P, Q), th) =>
- Goal.prove_global thy11 [] []
- (augment_sort thy1 pt_cp_sort
- (Logic.mk_implies (HOLogic.mk_Trueprop Q, HOLogic.mk_Trueprop P)))
- (fn _ => dtac (Thm.instantiate ([],
- [(cterm_of thy11 (Var (("pi", 0), permT)),
- cterm_of thy11 (Const ("List.rev", permT --> permT) $ pi))]) th) 1 THEN
- NominalPermeq.perm_simp_tac HOL_ss 1)) (ps ~~ ths)
- in (ths, ths') end) dt_atomTs);
-
- (** finite support **)
-
- val rec_fin_supp_thms = map (fn aT =>
- let
- val name = Long_Name.base_name (fst (dest_Type aT));
- val fs_name = PureThy.get_thm thy11 ("fs_" ^ name ^ "1");
- val aset = HOLogic.mk_setT aT;
- val finite = Const ("Finite_Set.finite", aset --> HOLogic.boolT);
- val fins = map (fn (f, T) => HOLogic.mk_Trueprop
- (finite $ (Const ("Nominal.supp", T --> aset) $ f)))
- (rec_fns ~~ rec_fn_Ts)
- in
- map (fn th => standard (th RS mp)) (split_conj_thm
- (Goal.prove_global thy11 []
- (map (augment_sort thy11 fs_cp_sort) fins)
- (augment_sort thy11 fs_cp_sort
- (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
- (map (fn (((T, U), R), i) =>
- let
- val x = Free ("x" ^ string_of_int i, T);
- val y = Free ("y" ^ string_of_int i, U)
- in
- HOLogic.mk_imp (R $ x $ y,
- finite $ (Const ("Nominal.supp", U --> aset) $ y))
- end) (recTs ~~ rec_result_Ts ~~ rec_sets ~~
- (1 upto length recTs))))))
- (fn {prems = fins, ...} =>
- (rtac rec_induct THEN_ALL_NEW cut_facts_tac fins) 1 THEN REPEAT
- (NominalPermeq.finite_guess_tac (HOL_ss addsimps [fs_name]) 1))))
- end) dt_atomTs;
-
- (** freshness **)
-
- val finite_premss = map (fn aT =>
- map (fn (f, T) => HOLogic.mk_Trueprop
- (Const ("Finite_Set.finite", HOLogic.mk_setT aT --> HOLogic.boolT) $
- (Const ("Nominal.supp", T --> HOLogic.mk_setT aT) $ f)))
- (rec_fns ~~ rec_fn_Ts)) dt_atomTs;
-
- val rec_fns' = map (augment_sort thy11 fs_cp_sort) rec_fns;
-
- val rec_fresh_thms = map (fn ((aT, eqvt_ths), finite_prems) =>
- let
- val name = Long_Name.base_name (fst (dest_Type aT));
- val fs_name = PureThy.get_thm thy11 ("fs_" ^ name ^ "1");
- val a = Free ("a", aT);
- val freshs = map (fn (f, fT) => HOLogic.mk_Trueprop
- (fresh_const aT fT $ a $ f)) (rec_fns ~~ rec_fn_Ts)
- in
- map (fn (((T, U), R), eqvt_th) =>
- let
- val x = Free ("x", augment_sort_typ thy11 fs_cp_sort T);
- val y = Free ("y", U);
- val y' = Free ("y'", U)
- in
- standard (Goal.prove (ProofContext.init thy11) []
- (map (augment_sort thy11 fs_cp_sort)
- (finite_prems @
- [HOLogic.mk_Trueprop (R $ x $ y),
- HOLogic.mk_Trueprop (HOLogic.mk_all ("y'", U,
- HOLogic.mk_imp (R $ x $ y', HOLogic.mk_eq (y', y)))),
- HOLogic.mk_Trueprop (fresh_const aT T $ a $ x)] @
- freshs))
- (HOLogic.mk_Trueprop (fresh_const aT U $ a $ y))
- (fn {prems, context} =>
- let
- val (finite_prems, rec_prem :: unique_prem ::
- fresh_prems) = chop (length finite_prems) prems;
- val unique_prem' = unique_prem RS spec RS mp;
- val unique = [unique_prem', unique_prem' RS sym] MRS trans;
- val _ $ (_ $ (_ $ S $ _)) $ _ = prop_of supports_fresh;
- val tuple = foldr1 HOLogic.mk_prod (x :: rec_fns')
- in EVERY
- [rtac (Drule.cterm_instantiate
- [(cterm_of thy11 S,
- cterm_of thy11 (Const ("Nominal.supp",
- fastype_of tuple --> HOLogic.mk_setT aT) $ tuple))]
- supports_fresh) 1,
- simp_tac (HOL_basic_ss addsimps
- [supports_def, symmetric fresh_def, fresh_prod]) 1,
- REPEAT_DETERM (resolve_tac [allI, impI] 1),
- REPEAT_DETERM (etac conjE 1),
- rtac unique 1,
- SUBPROOF (fn {prems = prems', params = [a, b], ...} => EVERY
- [cut_facts_tac [rec_prem] 1,
- rtac (Thm.instantiate ([],
- [(cterm_of thy11 (Var (("pi", 0), mk_permT aT)),
- cterm_of thy11 (perm_of_pair (term_of a, term_of b)))]) eqvt_th) 1,
- asm_simp_tac (HOL_ss addsimps
- (prems' @ perm_swap @ perm_fresh_fresh)) 1]) context 1,
- rtac rec_prem 1,
- simp_tac (HOL_ss addsimps (fs_name ::
- supp_prod :: finite_Un :: finite_prems)) 1,
- simp_tac (HOL_ss addsimps (symmetric fresh_def ::
- fresh_prod :: fresh_prems)) 1]
- end))
- end) (recTs ~~ rec_result_Ts ~~ rec_sets ~~ eqvt_ths)
- end) (dt_atomTs ~~ rec_equiv_thms' ~~ finite_premss);
-
- (** uniqueness **)
-
- val fun_tuple = foldr1 HOLogic.mk_prod (rec_ctxt :: rec_fns);
- val fun_tupleT = fastype_of fun_tuple;
- val rec_unique_frees =
- DatatypeProp.indexify_names (replicate (length recTs) "x") ~~ recTs;
- val rec_unique_frees'' = map (fn (s, T) => (s ^ "'", T)) rec_unique_frees;
- val rec_unique_frees' =
- DatatypeProp.indexify_names (replicate (length recTs) "y") ~~ rec_result_Ts;
- val rec_unique_concls = map (fn ((x, U), R) =>
- Const ("Ex1", (U --> HOLogic.boolT) --> HOLogic.boolT) $
- Abs ("y", U, R $ Free x $ Bound 0))
- (rec_unique_frees ~~ rec_result_Ts ~~ rec_sets);
-
- val induct_aux_rec = Drule.cterm_instantiate
- (map (pairself (cterm_of thy11) o apsnd (augment_sort thy11 fs_cp_sort))
- (map (fn (aT, f) => (Logic.varify f, Abs ("z", HOLogic.unitT,
- Const ("Nominal.supp", fun_tupleT --> HOLogic.mk_setT aT) $ fun_tuple)))
- fresh_fs @
- map (fn (((P, T), (x, U)), Q) =>
- (Var ((P, 0), Logic.varifyT (fsT' --> T --> HOLogic.boolT)),
- Abs ("z", HOLogic.unitT, absfree (x, U, Q))))
- (pnames ~~ recTs ~~ rec_unique_frees ~~ rec_unique_concls) @
- map (fn (s, T) => (Var ((s, 0), Logic.varifyT T), Free (s, T)))
- rec_unique_frees)) induct_aux;
-
- fun obtain_fresh_name vs ths rec_fin_supp T (freshs1, freshs2, ctxt) =
- let
- val p = foldr1 HOLogic.mk_prod (vs @ freshs1);
- val ex = Goal.prove ctxt [] [] (HOLogic.mk_Trueprop
- (HOLogic.exists_const T $ Abs ("x", T,
- fresh_const T (fastype_of p) $ Bound 0 $ p)))
- (fn _ => EVERY
- [cut_facts_tac ths 1,
- REPEAT_DETERM (dresolve_tac (the (AList.lookup op = rec_fin_supp T)) 1),
- resolve_tac exists_fresh' 1,
- asm_simp_tac (HOL_ss addsimps (supp_prod :: finite_Un :: fs_atoms)) 1]);
- val (([cx], ths), ctxt') = Obtain.result
- (fn _ => EVERY
- [etac exE 1,
- full_simp_tac (HOL_ss addsimps (fresh_prod :: fresh_atm)) 1,
- REPEAT (etac conjE 1)])
- [ex] ctxt
- in (freshs1 @ [term_of cx], freshs2 @ ths, ctxt') end;
-
- val finite_ctxt_prems = map (fn aT =>
- HOLogic.mk_Trueprop
- (Const ("Finite_Set.finite", HOLogic.mk_setT aT --> HOLogic.boolT) $
- (Const ("Nominal.supp", fsT' --> HOLogic.mk_setT aT) $ rec_ctxt))) dt_atomTs;
-
- val rec_unique_thms = split_conj_thm (Goal.prove
- (ProofContext.init thy11) (map fst rec_unique_frees)
- (map (augment_sort thy11 fs_cp_sort)
- (List.concat finite_premss @ finite_ctxt_prems @ rec_prems @ rec_prems'))
- (augment_sort thy11 fs_cp_sort
- (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj rec_unique_concls)))
- (fn {prems, context} =>
- let
- val k = length rec_fns;
- val (finite_thss, ths1) = fold_map (fn T => fn xs =>
- apfst (pair T) (chop k xs)) dt_atomTs prems;
- val (finite_ctxt_ths, ths2) = chop (length dt_atomTs) ths1;
- val (P_ind_ths, fcbs) = chop k ths2;
- val P_ths = map (fn th => th RS mp) (split_conj_thm
- (Goal.prove context
- (map fst (rec_unique_frees'' @ rec_unique_frees')) []
- (augment_sort thy11 fs_cp_sort
- (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
- (map (fn (((x, y), S), P) => HOLogic.mk_imp
- (S $ Free x $ Free y, P $ (Free y)))
- (rec_unique_frees'' ~~ rec_unique_frees' ~~
- rec_sets ~~ rec_preds)))))
- (fn _ =>
- rtac rec_induct 1 THEN
- REPEAT ((resolve_tac P_ind_ths THEN_ALL_NEW assume_tac) 1))));
- val rec_fin_supp_thms' = map
- (fn (ths, (T, fin_ths)) => (T, map (curry op MRS fin_ths) ths))
- (rec_fin_supp_thms ~~ finite_thss);
- in EVERY
- ([rtac induct_aux_rec 1] @
- maps (fn ((_, finite_ths), finite_th) =>
- [cut_facts_tac (finite_th :: finite_ths) 1,
- asm_simp_tac (HOL_ss addsimps [supp_prod, finite_Un]) 1])
- (finite_thss ~~ finite_ctxt_ths) @
- maps (fn ((_, idxss), elim) => maps (fn idxs =>
- [full_simp_tac (HOL_ss addsimps [symmetric fresh_def, supp_prod, Un_iff]) 1,
- REPEAT_DETERM (eresolve_tac [conjE, ex1E] 1),
- rtac ex1I 1,
- (resolve_tac rec_intrs THEN_ALL_NEW atac) 1,
- rotate_tac ~1 1,
- ((DETERM o etac elim) THEN_ALL_NEW full_simp_tac
- (HOL_ss addsimps List.concat distinct_thms)) 1] @
- (if null idxs then [] else [hyp_subst_tac 1,
- SUBPROOF (fn {asms, concl, prems = prems', params, context = context', ...} =>
- let
- val SOME prem = find_first (can (HOLogic.dest_eq o
- HOLogic.dest_Trueprop o prop_of)) prems';
- val _ $ (_ $ lhs $ rhs) = prop_of prem;
- val _ $ (_ $ lhs' $ rhs') = term_of concl;
- val rT = fastype_of lhs';
- val (c, cargsl) = strip_comb lhs;
- val cargsl' = partition_cargs idxs cargsl;
- val boundsl = List.concat (map fst cargsl');
- val (_, cargsr) = strip_comb rhs;
- val cargsr' = partition_cargs idxs cargsr;
- val boundsr = List.concat (map fst cargsr');
- val (params1, _ :: params2) =
- chop (length params div 2) (map term_of params);
- val params' = params1 @ params2;
- val rec_prems = filter (fn th => case prop_of th of
- _ $ p => (case head_of p of
- Const (s, _) => s mem rec_set_names
- | _ => false)
- | _ => false) prems';
- val fresh_prems = filter (fn th => case prop_of th of
- _ $ (Const ("Nominal.fresh", _) $ _ $ _) => true
- | _ $ (Const ("Not", _) $ _) => true
- | _ => false) prems';
- val Ts = map fastype_of boundsl;
-
- val _ = warning "step 1: obtaining fresh names";
- val (freshs1, freshs2, context'') = fold
- (obtain_fresh_name (rec_ctxt :: rec_fns' @ params')
- (List.concat (map snd finite_thss) @
- finite_ctxt_ths @ rec_prems)
- rec_fin_supp_thms')
- Ts ([], [], context');
- val pi1 = map perm_of_pair (boundsl ~~ freshs1);
- val rpi1 = rev pi1;
- val pi2 = map perm_of_pair (boundsr ~~ freshs1);
- val rpi2 = rev pi2;
-
- val fresh_prems' = mk_not_sym fresh_prems;
- val freshs2' = mk_not_sym freshs2;
-
- (** as, bs, cs # K as ts, K bs us **)
- val _ = warning "step 2: as, bs, cs # K as ts, K bs us";
- val prove_fresh_ss = HOL_ss addsimps
- (finite_Diff :: List.concat fresh_thms @
- fs_atoms @ abs_fresh @ abs_supp @ fresh_atm);
- (* FIXME: avoid asm_full_simp_tac ? *)
- fun prove_fresh ths y x = Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (fresh_const
- (fastype_of x) (fastype_of y) $ x $ y))
- (fn _ => cut_facts_tac ths 1 THEN asm_full_simp_tac prove_fresh_ss 1);
- val constr_fresh_thms =
- map (prove_fresh fresh_prems lhs) boundsl @
- map (prove_fresh fresh_prems rhs) boundsr @
- map (prove_fresh freshs2 lhs) freshs1 @
- map (prove_fresh freshs2 rhs) freshs1;
-
- (** pi1 o (K as ts) = pi2 o (K bs us) **)
- val _ = warning "step 3: pi1 o (K as ts) = pi2 o (K bs us)";
- val pi1_pi2_eq = Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (fold_rev (mk_perm []) pi1 lhs, fold_rev (mk_perm []) pi2 rhs)))
- (fn _ => EVERY
- [cut_facts_tac constr_fresh_thms 1,
- asm_simp_tac (HOL_basic_ss addsimps perm_fresh_fresh) 1,
- rtac prem 1]);
-
- (** pi1 o ts = pi2 o us **)
- val _ = warning "step 4: pi1 o ts = pi2 o us";
- val pi1_pi2_eqs = map (fn (t, u) =>
- Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (fold_rev (mk_perm []) pi1 t, fold_rev (mk_perm []) pi2 u)))
- (fn _ => EVERY
- [cut_facts_tac [pi1_pi2_eq] 1,
- asm_full_simp_tac (HOL_ss addsimps
- (calc_atm @ List.concat perm_simps' @
- fresh_prems' @ freshs2' @ abs_perm @
- alpha @ List.concat inject_thms)) 1]))
- (map snd cargsl' ~~ map snd cargsr');
-
- (** pi1^-1 o pi2 o us = ts **)
- val _ = warning "step 5: pi1^-1 o pi2 o us = ts";
- val rpi1_pi2_eqs = map (fn ((t, u), eq) =>
- Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (fold_rev (mk_perm []) (rpi1 @ pi2) u, t)))
- (fn _ => simp_tac (HOL_ss addsimps
- ((eq RS sym) :: perm_swap)) 1))
- (map snd cargsl' ~~ map snd cargsr' ~~ pi1_pi2_eqs);
-
- val (rec_prems1, rec_prems2) =
- chop (length rec_prems div 2) rec_prems;
-
- (** (ts, pi1^-1 o pi2 o vs) in rec_set **)
- val _ = warning "step 6: (ts, pi1^-1 o pi2 o vs) in rec_set";
- val rec_prems' = map (fn th =>
- let
- val _ $ (S $ x $ y) = prop_of th;
- val Const (s, _) = head_of S;
- val k = find_index (equal s) rec_set_names;
- val pi = rpi1 @ pi2;
- fun mk_pi z = fold_rev (mk_perm []) pi z;
- fun eqvt_tac p =
- let
- val U as Type (_, [Type (_, [T, _])]) = fastype_of p;
- val l = find_index (equal T) dt_atomTs;
- val th = List.nth (List.nth (rec_equiv_thms', l), k);
- val th' = Thm.instantiate ([],
- [(cterm_of thy11 (Var (("pi", 0), U)),
- cterm_of thy11 p)]) th;
- in rtac th' 1 end;
- val th' = Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (S $ mk_pi x $ mk_pi y))
- (fn _ => EVERY
- (map eqvt_tac pi @
- [simp_tac (HOL_ss addsimps (fresh_prems' @ freshs2' @
- perm_swap @ perm_fresh_fresh)) 1,
- rtac th 1]))
- in
- Simplifier.simplify
- (HOL_basic_ss addsimps rpi1_pi2_eqs) th'
- end) rec_prems2;
-
- val ihs = filter (fn th => case prop_of th of
- _ $ (Const ("All", _) $ _) => true | _ => false) prems';
-
- (** pi1 o rs = pi2 o vs , rs = pi1^-1 o pi2 o vs **)
- val _ = warning "step 7: pi1 o rs = pi2 o vs , rs = pi1^-1 o pi2 o vs";
- val rec_eqns = map (fn (th, ih) =>
- let
- val th' = th RS (ih RS spec RS mp) RS sym;
- val _ $ (_ $ lhs $ rhs) = prop_of th';
- fun strip_perm (_ $ _ $ t) = strip_perm t
- | strip_perm t = t;
- in
- Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (fold_rev (mk_perm []) pi1 lhs,
- fold_rev (mk_perm []) pi2 (strip_perm rhs))))
- (fn _ => simp_tac (HOL_basic_ss addsimps
- (th' :: perm_swap)) 1)
- end) (rec_prems' ~~ ihs);
-
- (** as # rs **)
- val _ = warning "step 8: as # rs";
- val rec_freshs = List.concat
- (map (fn (rec_prem, ih) =>
- let
- val _ $ (S $ x $ (y as Free (_, T))) =
- prop_of rec_prem;
- val k = find_index (equal S) rec_sets;
- val atoms = List.concat (List.mapPartial (fn (bs, z) =>
- if z = x then NONE else SOME bs) cargsl')
- in
- map (fn a as Free (_, aT) =>
- let val l = find_index (equal aT) dt_atomTs;
- in
- Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (fresh_const aT T $ a $ y))
- (fn _ => EVERY
- (rtac (List.nth (List.nth (rec_fresh_thms, l), k)) 1 ::
- map (fn th => rtac th 1)
- (snd (List.nth (finite_thss, l))) @
- [rtac rec_prem 1, rtac ih 1,
- REPEAT_DETERM (resolve_tac fresh_prems 1)]))
- end) atoms
- end) (rec_prems1 ~~ ihs));
-
- (** as # fK as ts rs , bs # fK bs us vs **)
- val _ = warning "step 9: as # fK as ts rs , bs # fK bs us vs";
- fun prove_fresh_result (a as Free (_, aT)) =
- Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (fresh_const aT rT $ a $ rhs'))
- (fn _ => EVERY
- [resolve_tac fcbs 1,
- REPEAT_DETERM (resolve_tac
- (fresh_prems @ rec_freshs) 1),
- REPEAT_DETERM (resolve_tac (maps snd rec_fin_supp_thms') 1
- THEN resolve_tac rec_prems 1),
- resolve_tac P_ind_ths 1,
- REPEAT_DETERM (resolve_tac (P_ths @ rec_prems) 1)]);
-
- val fresh_results'' = map prove_fresh_result boundsl;
-
- fun prove_fresh_result'' ((a as Free (_, aT), b), th) =
- let val th' = Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (fresh_const aT rT $
- fold_rev (mk_perm []) (rpi2 @ pi1) a $
- fold_rev (mk_perm []) (rpi2 @ pi1) rhs'))
- (fn _ => simp_tac (HOL_ss addsimps fresh_bij) 1 THEN
- rtac th 1)
- in
- Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (fresh_const aT rT $ b $ lhs'))
- (fn _ => EVERY
- [cut_facts_tac [th'] 1,
- full_simp_tac (Simplifier.theory_context thy11 HOL_ss
- addsimps rec_eqns @ pi1_pi2_eqs @ perm_swap
- addsimprocs [NominalPermeq.perm_simproc_app]) 1,
- full_simp_tac (HOL_ss addsimps (calc_atm @
- fresh_prems' @ freshs2' @ perm_fresh_fresh)) 1])
- end;
-
- val fresh_results = fresh_results'' @ map prove_fresh_result''
- (boundsl ~~ boundsr ~~ fresh_results'');
-
- (** cs # fK as ts rs , cs # fK bs us vs **)
- val _ = warning "step 10: cs # fK as ts rs , cs # fK bs us vs";
- fun prove_fresh_result' recs t (a as Free (_, aT)) =
- Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (fresh_const aT rT $ a $ t))
- (fn _ => EVERY
- [cut_facts_tac recs 1,
- REPEAT_DETERM (dresolve_tac
- (the (AList.lookup op = rec_fin_supp_thms' aT)) 1),
- NominalPermeq.fresh_guess_tac
- (HOL_ss addsimps (freshs2 @
- fs_atoms @ fresh_atm @
- List.concat (map snd finite_thss))) 1]);
-
- val fresh_results' =
- map (prove_fresh_result' rec_prems1 rhs') freshs1 @
- map (prove_fresh_result' rec_prems2 lhs') freshs1;
-
- (** pi1 o (fK as ts rs) = pi2 o (fK bs us vs) **)
- val _ = warning "step 11: pi1 o (fK as ts rs) = pi2 o (fK bs us vs)";
- val pi1_pi2_result = Goal.prove context'' [] []
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (fold_rev (mk_perm []) pi1 rhs', fold_rev (mk_perm []) pi2 lhs')))
- (fn _ => simp_tac (Simplifier.context context'' HOL_ss
- addsimps pi1_pi2_eqs @ rec_eqns
- addsimprocs [NominalPermeq.perm_simproc_app]) 1 THEN
- TRY (simp_tac (HOL_ss addsimps
- (fresh_prems' @ freshs2' @ calc_atm @ perm_fresh_fresh)) 1));
-
- val _ = warning "final result";
- val final = Goal.prove context'' [] [] (term_of concl)
- (fn _ => cut_facts_tac [pi1_pi2_result RS sym] 1 THEN
- full_simp_tac (HOL_basic_ss addsimps perm_fresh_fresh @
- fresh_results @ fresh_results') 1);
- val final' = ProofContext.export context'' context' [final];
- val _ = warning "finished!"
- in
- resolve_tac final' 1
- end) context 1])) idxss) (ndescr ~~ rec_elims))
- end));
-
- val rec_total_thms = map (fn r => r RS theI') rec_unique_thms;
-
- (* define primrec combinators *)
-
- val big_reccomb_name = (space_implode "_" new_type_names) ^ "_rec";
- val reccomb_names = map (Sign.full_bname thy11)
- (if length descr'' = 1 then [big_reccomb_name] else
- (map ((curry (op ^) (big_reccomb_name ^ "_")) o string_of_int)
- (1 upto (length descr''))));
- val reccombs = map (fn ((name, T), T') => list_comb
- (Const (name, rec_fn_Ts @ [T] ---> T'), rec_fns))
- (reccomb_names ~~ recTs ~~ rec_result_Ts);
-
- val (reccomb_defs, thy12) =
- thy11
- |> Sign.add_consts_i (map (fn ((name, T), T') =>
- (Binding.name (Long_Name.base_name name), rec_fn_Ts @ [T] ---> T', NoSyn))
- (reccomb_names ~~ recTs ~~ rec_result_Ts))
- |> (PureThy.add_defs false o map Thm.no_attributes) (map (fn ((((name, comb), set), T), T') =>
- (Binding.name (Long_Name.base_name name ^ "_def"), Logic.mk_equals (comb, absfree ("x", T,
- Const ("The", (T' --> HOLogic.boolT) --> T') $ absfree ("y", T',
- set $ Free ("x", T) $ Free ("y", T'))))))
- (reccomb_names ~~ reccombs ~~ rec_sets ~~ recTs ~~ rec_result_Ts));
-
- (* prove characteristic equations for primrec combinators *)
-
- val rec_thms = map (fn (prems, concl) =>
- let
- val _ $ (_ $ (_ $ x) $ _) = concl;
- val (_, cargs) = strip_comb x;
- val ps = map (fn (x as Free (_, T), i) =>
- (Free ("x" ^ string_of_int i, T), x)) (cargs ~~ (1 upto length cargs));
- val concl' = subst_atomic_types (rec_result_Ts' ~~ rec_result_Ts) concl;
- val prems' = List.concat finite_premss @ finite_ctxt_prems @
- rec_prems @ rec_prems' @ map (subst_atomic ps) prems;
- fun solve rules prems = resolve_tac rules THEN_ALL_NEW
- (resolve_tac prems THEN_ALL_NEW atac)
- in
- Goal.prove_global thy12 []
- (map (augment_sort thy12 fs_cp_sort) prems')
- (augment_sort thy12 fs_cp_sort concl')
- (fn {prems, ...} => EVERY
- [rewrite_goals_tac reccomb_defs,
- rtac the1_equality 1,
- solve rec_unique_thms prems 1,
- resolve_tac rec_intrs 1,
- REPEAT (solve (prems @ rec_total_thms) prems 1)])
- end) (rec_eq_prems ~~
- DatatypeProp.make_primrecs new_type_names descr' sorts thy12);
-
- val dt_infos = map (make_dt_info pdescr sorts induct reccomb_names rec_thms)
- ((0 upto length descr1 - 1) ~~ descr1 ~~ distinct_thms ~~ inject_thms);
-
- (* FIXME: theorems are stored in database for testing only *)
- val (_, thy13) = thy12 |>
- PureThy.add_thmss
- [((Binding.name "rec_equiv", List.concat rec_equiv_thms), []),
- ((Binding.name "rec_equiv'", List.concat rec_equiv_thms'), []),
- ((Binding.name "rec_fin_supp", List.concat rec_fin_supp_thms), []),
- ((Binding.name "rec_fresh", List.concat rec_fresh_thms), []),
- ((Binding.name "rec_unique", map standard rec_unique_thms), []),
- ((Binding.name "recs", rec_thms), [])] ||>
- Sign.parent_path ||>
- map_nominal_datatypes (fold Symtab.update dt_infos);
-
- in
- thy13
- end;
-
-val add_nominal_datatype = gen_add_nominal_datatype DatatypePackage.read_typ;
-
-
-(* FIXME: The following stuff should be exported by DatatypePackage *)
-
-local structure P = OuterParse and K = OuterKeyword in
-
-val datatype_decl =
- Scan.option (P.$$$ "(" |-- P.name --| P.$$$ ")") -- P.type_args -- P.name -- P.opt_infix --
- (P.$$$ "=" |-- P.enum1 "|" (P.name -- Scan.repeat P.typ -- P.opt_mixfix));
-
-fun mk_datatype args =
- let
- val names = map (fn ((((NONE, _), t), _), _) => t | ((((SOME t, _), _), _), _) => t) args;
- val specs = map (fn ((((_, vs), t), mx), cons) =>
- (vs, t, mx, map (fn ((x, y), z) => (x, y, z)) cons)) args;
- in add_nominal_datatype DatatypeAux.default_datatype_config names specs end;
-
-val _ =
- OuterSyntax.command "nominal_datatype" "define inductive datatypes" K.thy_decl
- (P.and_list1 datatype_decl >> (Toplevel.theory o mk_datatype));
-
-end;
-
-end
--- a/src/HOL/Nominal/nominal_primrec.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Nominal/nominal_primrec.ML Fri Jun 19 21:08:07 2009 +0200
@@ -3,7 +3,7 @@
Author: Stefan Berghofer, TU Muenchen
Package for defining functions on nominal datatypes by primitive recursion.
-Taken from HOL/Tools/primrec_package.ML
+Taken from HOL/Tools/primrec.ML
*)
signature NOMINAL_PRIMREC =
@@ -223,7 +223,7 @@
(* find datatypes which contain all datatypes in tnames' *)
-fun find_dts (dt_info : NominalPackage.nominal_datatype_info Symtab.table) _ [] = []
+fun find_dts (dt_info : Nominal.nominal_datatype_info Symtab.table) _ [] = []
| find_dts dt_info tnames' (tname::tnames) =
(case Symtab.lookup dt_info tname of
NONE => primrec_err (quote tname ^ " is not a nominal datatype")
@@ -247,7 +247,7 @@
val eqns' = map unquantify spec'
val eqns = fold_rev (process_eqn lthy (fn v => Variable.is_fixed lthy v
orelse exists (fn ((w, _), _) => v = Binding.name_of w) fixes)) spec' [];
- val dt_info = NominalPackage.get_nominal_datatypes (ProofContext.theory_of lthy);
+ val dt_info = Nominal.get_nominal_datatypes (ProofContext.theory_of lthy);
val lsrs :: lsrss = maps (fn (_, (_, _, eqns)) =>
map (fn (_, (ls, _, rs, _, _)) => ls @ rs) eqns) eqns
val _ =
--- a/src/HOL/Product_Type.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Product_Type.thy Fri Jun 19 21:08:07 2009 +0200
@@ -9,7 +9,7 @@
imports Inductive
uses
("Tools/split_rule.ML")
- ("Tools/inductive_set_package.ML")
+ ("Tools/inductive_set.ML")
("Tools/inductive_realizer.ML")
("Tools/datatype_package/datatype_realizer.ML")
begin
@@ -1151,8 +1151,8 @@
use "Tools/inductive_realizer.ML"
setup InductiveRealizer.setup
-use "Tools/inductive_set_package.ML"
-setup InductiveSetPackage.setup
+use "Tools/inductive_set.ML"
+setup Inductive_Set.setup
use "Tools/datatype_package/datatype_realizer.ML"
setup DatatypeRealizer.setup
--- a/src/HOL/Recdef.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Recdef.thy Fri Jun 19 21:08:07 2009 +0200
@@ -16,7 +16,7 @@
("Tools/TFL/thry.ML")
("Tools/TFL/tfl.ML")
("Tools/TFL/post.ML")
- ("Tools/recdef_package.ML")
+ ("Tools/recdef.ML")
begin
text{** This form avoids giant explosions in proofs. NOTE USE OF ==*}
@@ -76,8 +76,8 @@
use "Tools/TFL/thry.ML"
use "Tools/TFL/tfl.ML"
use "Tools/TFL/post.ML"
-use "Tools/recdef_package.ML"
-setup RecdefPackage.setup
+use "Tools/recdef.ML"
+setup Recdef.setup
lemmas [recdef_simp] =
inv_image_def
--- a/src/HOL/Record.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Record.thy Fri Jun 19 21:08:07 2009 +0200
@@ -1,5 +1,4 @@
(* Title: HOL/Record.thy
- ID: $Id$
Author: Wolfgang Naraschewski, Norbert Schirmer and Markus Wenzel, TU Muenchen
*)
@@ -7,7 +6,7 @@
theory Record
imports Product_Type
-uses ("Tools/record_package.ML")
+uses ("Tools/record.ML")
begin
lemma prop_subst: "s = t \<Longrightarrow> PROP P t \<Longrightarrow> PROP P s"
@@ -56,7 +55,7 @@
"_record_scheme" :: "[fields, 'a] => 'a" ("(3\<lparr>_,/ (2\<dots> =/ _)\<rparr>)")
"_record_update" :: "['a, updates] => 'b" ("_/(3\<lparr>_\<rparr>)" [900,0] 900)
-use "Tools/record_package.ML"
-setup RecordPackage.setup
+use "Tools/record.ML"
+setup Record.setup
end
--- a/src/HOL/Statespace/state_fun.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Statespace/state_fun.ML Fri Jun 19 21:08:07 2009 +0200
@@ -74,7 +74,7 @@
val string_eq_simp_tac =
simp_tac (HOL_basic_ss
addsimps (thms "list.inject"@thms "char.inject"@simp_thms)
- addsimprocs [DatatypePackage.distinct_simproc,lazy_conj_simproc]
+ addsimprocs [Datatype.distinct_simproc,lazy_conj_simproc]
addcongs [thm "block_conj_cong"])
end;
@@ -89,7 +89,7 @@
in
val lookup_ss = (HOL_basic_ss
addsimps (thms "list.inject"@thms "char.inject"@simp_thms@rules)
- addsimprocs [DatatypePackage.distinct_simproc,lazy_conj_simproc]
+ addsimprocs [Datatype.distinct_simproc,lazy_conj_simproc]
addcongs [thm "block_conj_cong"]
addSolver StateSpace.distinctNameSolver)
end;
@@ -167,7 +167,7 @@
val meta_ext = thm "StateFun.meta_ext";
val o_apply = thm "Fun.o_apply";
val ss' = (HOL_ss addsimps (update_apply::o_apply::thms "list.inject"@thms "char.inject")
- addsimprocs [DatatypePackage.distinct_simproc,lazy_conj_simproc,StateSpace.distinct_simproc]
+ addsimprocs [Datatype.distinct_simproc,lazy_conj_simproc,StateSpace.distinct_simproc]
addcongs [thm "block_conj_cong"]);
in
val update_simproc =
@@ -267,7 +267,7 @@
val swap_ex_eq = thm "StateFun.swap_ex_eq";
fun is_selector thy T sel =
let
- val (flds,more) = RecordPackage.get_recT_fields thy T
+ val (flds,more) = Record.get_recT_fields thy T
in member (fn (s,(n,_)) => n=s) (more::flds) sel
end;
in
@@ -340,7 +340,7 @@
| mkName (TFree (x,_)) = mkUpper (Long_Name.base_name x)
| mkName (TVar ((x,_),_)) = mkUpper (Long_Name.base_name x);
-fun is_datatype thy n = is_some (Symtab.lookup (DatatypePackage.get_datatypes thy) n);
+fun is_datatype thy n = is_some (Symtab.lookup (Datatype.get_datatypes thy) n);
fun mk_map "List.list" = Syntax.const "List.map"
| mk_map n = Syntax.const ("StateFun.map_" ^ Long_Name.base_name n);
--- a/src/HOL/Statespace/state_space.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Statespace/state_space.ML Fri Jun 19 21:08:07 2009 +0200
@@ -585,8 +585,8 @@
end
handle ERROR msg => cat_error msg ("Failed to define statespace " ^ quote name);
-val define_statespace = gen_define_statespace RecordPackage.read_typ NONE;
-val define_statespace_i = gen_define_statespace RecordPackage.cert_typ;
+val define_statespace = gen_define_statespace Record.read_typ NONE;
+val define_statespace_i = gen_define_statespace Record.cert_typ;
(*** parse/print - translations ***)
--- a/src/HOL/Tools/TFL/casesplit.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/TFL/casesplit.ML Fri Jun 19 21:08:07 2009 +0200
@@ -90,7 +90,7 @@
(* get the case_thm (my version) from a type *)
fun case_thm_of_ty sgn ty =
let
- val dtypestab = DatatypePackage.get_datatypes sgn;
+ val dtypestab = Datatype.get_datatypes sgn;
val ty_str = case ty of
Type(ty_str, _) => ty_str
| TFree(s,_) => error ("Free type: " ^ s)
--- a/src/HOL/Tools/TFL/tfl.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/TFL/tfl.ML Fri Jun 19 21:08:07 2009 +0200
@@ -446,7 +446,7 @@
slow.*)
val case_ss = Simplifier.theory_context theory
(HOL_basic_ss addcongs
- (map (#weak_case_cong o snd) o Symtab.dest o DatatypePackage.get_datatypes) theory addsimps case_rewrites)
+ (map (#weak_case_cong o snd) o Symtab.dest o Datatype.get_datatypes) theory addsimps case_rewrites)
val corollaries' = map (Simplifier.simplify case_ss) corollaries
val extract = R.CONTEXT_REWRITE_RULE
(f, [R], @{thm cut_apply}, meta_tflCongs@context_congs)
--- a/src/HOL/Tools/TFL/thry.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/TFL/thry.ML Fri Jun 19 21:08:07 2009 +0200
@@ -60,20 +60,20 @@
*---------------------------------------------------------------------------*)
fun match_info thy dtco =
- case (DatatypePackage.get_datatype thy dtco,
- DatatypePackage.get_datatype_constrs thy dtco) of
+ case (Datatype.get_datatype thy dtco,
+ Datatype.get_datatype_constrs thy dtco) of
(SOME { case_name, ... }, SOME constructors) =>
SOME {case_const = Const (case_name, Sign.the_const_type thy case_name), constructors = map Const constructors}
| _ => NONE;
-fun induct_info thy dtco = case DatatypePackage.get_datatype thy dtco of
+fun induct_info thy dtco = case Datatype.get_datatype thy dtco of
NONE => NONE
| SOME {nchotomy, ...} =>
SOME {nchotomy = nchotomy,
- constructors = (map Const o the o DatatypePackage.get_datatype_constrs thy) dtco};
+ constructors = (map Const o the o Datatype.get_datatype_constrs thy) dtco};
fun extract_info thy =
- let val infos = (map snd o Symtab.dest o DatatypePackage.get_datatypes) thy
+ let val infos = (map snd o Symtab.dest o Datatype.get_datatypes) thy
in {case_congs = map (mk_meta_eq o #case_cong) infos,
case_rewrites = List.concat (map (map mk_meta_eq o #case_rewrites) infos)}
end;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/choice_specification.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,257 @@
+(* Title: HOL/Tools/choice_specification.ML
+ Author: Sebastian Skalberg, TU Muenchen
+
+Package for defining constants by specification.
+*)
+
+signature CHOICE_SPECIFICATION =
+sig
+ val add_specification: string option -> (bstring * xstring * bool) list ->
+ theory * thm -> theory * thm
+end
+
+structure Choice_Specification: CHOICE_SPECIFICATION =
+struct
+
+(* actual code *)
+
+local
+ fun mk_definitional [] arg = arg
+ | mk_definitional ((thname,cname,covld)::cos) (thy,thm) =
+ case HOLogic.dest_Trueprop (concl_of thm) of
+ Const("Ex",_) $ P =>
+ let
+ val ctype = domain_type (type_of P)
+ val cname_full = Sign.intern_const thy cname
+ val cdefname = if thname = ""
+ then Thm.def_name (Long_Name.base_name cname)
+ else thname
+ val def_eq = Logic.mk_equals (Const(cname_full,ctype),
+ HOLogic.choice_const ctype $ P)
+ val (thms, thy') = PureThy.add_defs covld [((Binding.name cdefname, def_eq),[])] thy
+ val thm' = [thm,hd thms] MRS @{thm exE_some}
+ in
+ mk_definitional cos (thy',thm')
+ end
+ | _ => raise THM ("Internal error: Bad specification theorem",0,[thm])
+
+ fun mk_axiomatic axname cos arg =
+ let
+ fun process [] (thy,tm) =
+ let
+ val (thms, thy') = PureThy.add_axioms [((Binding.name axname, HOLogic.mk_Trueprop tm),[])] thy
+ in
+ (thy',hd thms)
+ end
+ | process ((thname,cname,covld)::cos) (thy,tm) =
+ case tm of
+ Const("Ex",_) $ P =>
+ let
+ val ctype = domain_type (type_of P)
+ val cname_full = Sign.intern_const thy cname
+ val cdefname = if thname = ""
+ then Thm.def_name (Long_Name.base_name cname)
+ else thname
+ val co = Const(cname_full,ctype)
+ val thy' = Theory.add_finals_i covld [co] thy
+ val tm' = case P of
+ Abs(_, _, bodt) => subst_bound (co, bodt)
+ | _ => P $ co
+ in
+ process cos (thy',tm')
+ end
+ | _ => raise TERM ("Internal error: Bad specification theorem",[tm])
+ in
+ process cos arg
+ end
+
+in
+fun proc_exprop axiomatic cos arg =
+ case axiomatic of
+ SOME axname => mk_axiomatic axname cos (apsnd (HOLogic.dest_Trueprop o concl_of) arg)
+ | NONE => mk_definitional cos arg
+end
+
+fun add_specification axiomatic cos arg =
+ arg |> apsnd Thm.freezeT
+ |> proc_exprop axiomatic cos
+ |> apsnd standard
+
+
+(* Collect all intances of constants in term *)
+
+fun collect_consts ( t $ u,tms) = collect_consts (u,collect_consts (t,tms))
+ | collect_consts ( Abs(_,_,t),tms) = collect_consts (t,tms)
+ | collect_consts (tm as Const _,tms) = insert (op aconv) tm tms
+ | collect_consts ( _,tms) = tms
+
+(* Complementing Type.varify... *)
+
+fun unvarify t fmap =
+ let
+ val fmap' = map Library.swap fmap
+ fun unthaw (f as (a, S)) =
+ (case AList.lookup (op =) fmap' a of
+ NONE => TVar f
+ | SOME (b, _) => TFree (b, S))
+ in
+ map_types (map_type_tvar unthaw) t
+ end
+
+(* The syntactic meddling needed to setup add_specification for work *)
+
+fun process_spec axiomatic cos alt_props thy =
+ let
+ fun zip3 [] [] [] = []
+ | zip3 (x::xs) (y::ys) (z::zs) = (x,y,z)::zip3 xs ys zs
+ | zip3 _ _ _ = error "Choice_Specification.process_spec internal error"
+
+ fun myfoldr f [x] = x
+ | myfoldr f (x::xs) = f (x,myfoldr f xs)
+ | myfoldr f [] = error "Choice_Specification.process_spec internal error"
+
+ val rew_imps = alt_props |>
+ map (ObjectLogic.atomize o Thm.cterm_of thy o Syntax.read_prop_global thy o snd)
+ val props' = rew_imps |>
+ map (HOLogic.dest_Trueprop o term_of o snd o Thm.dest_equals o cprop_of)
+
+ fun proc_single prop =
+ let
+ val frees = OldTerm.term_frees prop
+ val _ = forall (fn v => Sign.of_sort thy (type_of v,HOLogic.typeS)) frees
+ orelse error "Specificaton: Only free variables of sort 'type' allowed"
+ val prop_closed = List.foldr (fn ((vname,T),prop) => HOLogic.mk_all (vname,T,prop)) prop (map dest_Free frees)
+ in
+ (prop_closed,frees)
+ end
+
+ val props'' = map proc_single props'
+ val frees = map snd props''
+ val prop = myfoldr HOLogic.mk_conj (map fst props'')
+ val cprop = cterm_of thy (HOLogic.mk_Trueprop prop)
+
+ val (vmap, prop_thawed) = Type.varify [] prop
+ val thawed_prop_consts = collect_consts (prop_thawed,[])
+ val (altcos,overloaded) = Library.split_list cos
+ val (names,sconsts) = Library.split_list altcos
+ val consts = map (Syntax.read_term_global thy) sconsts
+ val _ = not (Library.exists (not o Term.is_Const) consts)
+ orelse error "Specification: Non-constant found as parameter"
+
+ fun proc_const c =
+ let
+ val (_, c') = Type.varify [] c
+ val (cname,ctyp) = dest_Const c'
+ in
+ case List.filter (fn t => let val (name,typ) = dest_Const t
+ in name = cname andalso Sign.typ_equiv thy (typ, ctyp)
+ end) thawed_prop_consts of
+ [] => error ("Specification: No suitable instances of constant \"" ^ Syntax.string_of_term_global thy c ^ "\" found")
+ | [cf] => unvarify cf vmap
+ | _ => error ("Specification: Several variations of \"" ^ Syntax.string_of_term_global thy c ^ "\" found (try applying explicit type constraints)")
+ end
+ val proc_consts = map proc_const consts
+ fun mk_exist (c,prop) =
+ let
+ val T = type_of c
+ val cname = Long_Name.base_name (fst (dest_Const c))
+ val vname = if Syntax.is_identifier cname
+ then cname
+ else "x"
+ in
+ HOLogic.exists_const T $ Abs(vname,T,Term.abstract_over (c,prop))
+ end
+ val ex_prop = List.foldr mk_exist prop proc_consts
+ val cnames = map (fst o dest_Const) proc_consts
+ fun post_process (arg as (thy,thm)) =
+ let
+ fun inst_all thy (thm,v) =
+ let
+ val cv = cterm_of thy v
+ val cT = ctyp_of_term cv
+ val spec' = instantiate' [SOME cT] [NONE,SOME cv] spec
+ in
+ thm RS spec'
+ end
+ fun remove_alls frees thm =
+ Library.foldl (inst_all (Thm.theory_of_thm thm)) (thm,frees)
+ fun process_single ((name,atts),rew_imp,frees) args =
+ let
+ fun undo_imps thm =
+ equal_elim (symmetric rew_imp) thm
+
+ fun add_final (arg as (thy, thm)) =
+ if name = ""
+ then arg |> Library.swap
+ else (writeln (" " ^ name ^ ": " ^ (Display.string_of_thm thm));
+ PureThy.store_thm (Binding.name name, thm) thy)
+ in
+ args |> apsnd (remove_alls frees)
+ |> apsnd undo_imps
+ |> apsnd standard
+ |> Thm.theory_attributes (map (Attrib.attribute thy) atts)
+ |> add_final
+ |> Library.swap
+ end
+
+ fun process_all [proc_arg] args =
+ process_single proc_arg args
+ | process_all (proc_arg::rest) (thy,thm) =
+ let
+ val single_th = thm RS conjunct1
+ val rest_th = thm RS conjunct2
+ val (thy',_) = process_single proc_arg (thy,single_th)
+ in
+ process_all rest (thy',rest_th)
+ end
+ | process_all [] _ = error "Choice_Specification.process_spec internal error"
+ val alt_names = map fst alt_props
+ val _ = if exists (fn(name,_) => not (name = "")) alt_names
+ then writeln "specification"
+ else ()
+ in
+ arg |> apsnd Thm.freezeT
+ |> process_all (zip3 alt_names rew_imps frees)
+ end
+
+ fun after_qed [[thm]] = ProofContext.theory (fn thy =>
+ #1 (post_process (add_specification axiomatic (zip3 names cnames overloaded) (thy, thm))));
+ in
+ thy
+ |> ProofContext.init
+ |> Proof.theorem_i NONE after_qed [[(HOLogic.mk_Trueprop ex_prop, [])]]
+ end;
+
+
+(* outer syntax *)
+
+local structure P = OuterParse and K = OuterKeyword in
+
+val opt_name = Scan.optional (P.name --| P.$$$ ":") ""
+val opt_overloaded = P.opt_keyword "overloaded";
+
+val specification_decl =
+ P.$$$ "(" |-- Scan.repeat1 (opt_name -- P.term -- opt_overloaded) --| P.$$$ ")" --
+ Scan.repeat1 ((SpecParse.opt_thm_name ":" >> apfst Binding.name_of) -- P.prop)
+
+val _ =
+ OuterSyntax.command "specification" "define constants by specification" K.thy_goal
+ (specification_decl >> (fn (cos,alt_props) =>
+ Toplevel.print o (Toplevel.theory_to_proof
+ (process_spec NONE cos alt_props))))
+
+val ax_specification_decl =
+ P.name --
+ (P.$$$ "(" |-- Scan.repeat1 (opt_name -- P.term -- opt_overloaded) --| P.$$$ ")" --
+ Scan.repeat1 ((SpecParse.opt_thm_name ":" >> apfst Binding.name_of) -- P.prop))
+
+val _ =
+ OuterSyntax.command "ax_specification" "define constants by specification" K.thy_goal
+ (ax_specification_decl >> (fn (axname,(cos,alt_props)) =>
+ Toplevel.print o (Toplevel.theory_to_proof
+ (process_spec (SOME axname) cos alt_props))))
+
+end
+
+
+end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/datatype_package/datatype.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,705 @@
+(* Title: HOL/Tools/datatype.ML
+ Author: Stefan Berghofer, TU Muenchen
+
+Datatype package for Isabelle/HOL.
+*)
+
+signature DATATYPE =
+sig
+ type datatype_config = DatatypeAux.datatype_config
+ type datatype_info = DatatypeAux.datatype_info
+ type descr = DatatypeAux.descr
+ val get_datatypes : theory -> datatype_info Symtab.table
+ val get_datatype : theory -> string -> datatype_info option
+ val the_datatype : theory -> string -> datatype_info
+ val datatype_of_constr : theory -> string -> datatype_info option
+ val datatype_of_case : theory -> string -> datatype_info option
+ val the_datatype_spec : theory -> string -> (string * sort) list * (string * typ list) list
+ val the_datatype_descr : theory -> string list
+ -> descr * (string * sort) list * string list
+ * (string list * string list) * (typ list * typ list)
+ val get_datatype_constrs : theory -> string -> (string * typ) list option
+ val distinct_simproc : simproc
+ val make_case : Proof.context -> bool -> string list -> term ->
+ (term * term) list -> term * (term * (int * bool)) list
+ val strip_case : Proof.context -> bool -> term -> (term * (term * term) list) option
+ val read_typ: theory ->
+ (typ list * (string * sort) list) * string -> typ list * (string * sort) list
+ val interpretation : (datatype_config -> string list -> theory -> theory) -> theory -> theory
+ type rules = {distinct : thm list list,
+ inject : thm list list,
+ exhaustion : thm list,
+ rec_thms : thm list,
+ case_thms : thm list list,
+ split_thms : (thm * thm) list,
+ induction : thm,
+ simps : thm list}
+ val rep_datatype : datatype_config -> (rules -> Proof.context -> Proof.context)
+ -> string list option -> term list -> theory -> Proof.state;
+ val rep_datatype_cmd : string list option -> string list -> theory -> Proof.state
+ val add_datatype : datatype_config -> string list -> (string list * binding * mixfix *
+ (binding * typ list * mixfix) list) list -> theory -> rules * theory
+ val add_datatype_cmd : string list -> (string list * binding * mixfix *
+ (binding * string list * mixfix) list) list -> theory -> rules * theory
+ val setup: theory -> theory
+ val print_datatypes : theory -> unit
+end;
+
+structure Datatype : DATATYPE =
+struct
+
+open DatatypeAux;
+
+
+(* theory data *)
+
+structure DatatypesData = TheoryDataFun
+(
+ type T =
+ {types: datatype_info Symtab.table,
+ constrs: datatype_info Symtab.table,
+ cases: datatype_info Symtab.table};
+
+ val empty =
+ {types = Symtab.empty, constrs = Symtab.empty, cases = Symtab.empty};
+ val copy = I;
+ val extend = I;
+ fun merge _
+ ({types = types1, constrs = constrs1, cases = cases1},
+ {types = types2, constrs = constrs2, cases = cases2}) =
+ {types = Symtab.merge (K true) (types1, types2),
+ constrs = Symtab.merge (K true) (constrs1, constrs2),
+ cases = Symtab.merge (K true) (cases1, cases2)};
+);
+
+val get_datatypes = #types o DatatypesData.get;
+val map_datatypes = DatatypesData.map;
+
+fun print_datatypes thy =
+ Pretty.writeln (Pretty.strs ("datatypes:" ::
+ map #1 (NameSpace.extern_table (Sign.type_space thy, get_datatypes thy))));
+
+
+(** theory information about datatypes **)
+
+fun put_dt_infos (dt_infos : (string * datatype_info) list) =
+ map_datatypes (fn {types, constrs, cases} =>
+ {types = fold Symtab.update dt_infos types,
+ constrs = fold Symtab.default (*conservative wrt. overloaded constructors*)
+ (maps (fn (_, info as {descr, index, ...}) => map (rpair info o fst)
+ (#3 (the (AList.lookup op = descr index)))) dt_infos) constrs,
+ cases = fold Symtab.update
+ (map (fn (_, info as {case_name, ...}) => (case_name, info)) dt_infos)
+ cases});
+
+val get_datatype = Symtab.lookup o get_datatypes;
+
+fun the_datatype thy name = (case get_datatype thy name of
+ SOME info => info
+ | NONE => error ("Unknown datatype " ^ quote name));
+
+val datatype_of_constr = Symtab.lookup o #constrs o DatatypesData.get;
+val datatype_of_case = Symtab.lookup o #cases o DatatypesData.get;
+
+fun get_datatype_descr thy dtco =
+ get_datatype thy dtco
+ |> Option.map (fn info as { descr, index, ... } =>
+ (info, (((fn SOME (_, dtys, cos) => (dtys, cos)) o AList.lookup (op =) descr) index)));
+
+fun the_datatype_spec thy dtco =
+ let
+ val info as { descr, index, sorts = raw_sorts, ... } = the_datatype thy dtco;
+ val SOME (_, dtys, raw_cos) = AList.lookup (op =) descr index;
+ val sorts = map ((fn v => (v, (the o AList.lookup (op =) raw_sorts) v))
+ o DatatypeAux.dest_DtTFree) dtys;
+ val cos = map
+ (fn (co, tys) => (co, map (DatatypeAux.typ_of_dtyp descr sorts) tys)) raw_cos;
+ in (sorts, cos) end;
+
+fun the_datatype_descr thy (raw_tycos as raw_tyco :: _) =
+ let
+ val info = the_datatype thy raw_tyco;
+ val descr = #descr info;
+
+ val SOME (_, dtys, raw_cos) = AList.lookup (op =) descr (#index info);
+ val vs = map ((fn v => (v, (the o AList.lookup (op =) (#sorts info)) v))
+ o dest_DtTFree) dtys;
+
+ fun is_DtTFree (DtTFree _) = true
+ | is_DtTFree _ = false
+ val k = find_index (fn (_, (_, dTs, _)) => not (forall is_DtTFree dTs)) descr;
+ val protoTs as (dataTs, _) = chop k descr
+ |> (pairself o map) (fn (_, (tyco, dTs, _)) => (tyco, map (typ_of_dtyp descr vs) dTs));
+
+ val tycos = map fst dataTs;
+ val _ = if gen_eq_set (op =) (tycos, raw_tycos) then ()
+ else error ("Type constructors " ^ commas (map quote raw_tycos)
+ ^ "do not belong exhaustively to one mutual recursive datatype");
+
+ val (Ts, Us) = (pairself o map) Type protoTs;
+
+ val names = map Long_Name.base_name (the_default tycos (#alt_names info));
+ val (auxnames, _) = Name.make_context names
+ |> fold_map (yield_singleton Name.variants o name_of_typ) Us
+
+ in (descr, vs, tycos, (names, auxnames), (Ts, Us)) end;
+
+fun get_datatype_constrs thy dtco =
+ case try (the_datatype_spec thy) dtco
+ of SOME (sorts, cos) =>
+ let
+ fun subst (v, sort) = TVar ((v, 0), sort);
+ fun subst_ty (TFree v) = subst v
+ | subst_ty ty = ty;
+ val dty = Type (dtco, map subst sorts);
+ fun mk_co (co, tys) = (co, map (Term.map_atyps subst_ty) tys ---> dty);
+ in SOME (map mk_co cos) end
+ | NONE => NONE;
+
+
+(** induct method setup **)
+
+(* case names *)
+
+local
+
+fun dt_recs (DtTFree _) = []
+ | dt_recs (DtType (_, dts)) = maps dt_recs dts
+ | dt_recs (DtRec i) = [i];
+
+fun dt_cases (descr: descr) (_, args, constrs) =
+ let
+ fun the_bname i = Long_Name.base_name (#1 (the (AList.lookup (op =) descr i)));
+ val bnames = map the_bname (distinct (op =) (maps dt_recs args));
+ in map (fn (c, _) => space_implode "_" (Long_Name.base_name c :: bnames)) constrs end;
+
+
+fun induct_cases descr =
+ DatatypeProp.indexify_names (maps (dt_cases descr) (map #2 descr));
+
+fun exhaust_cases descr i = dt_cases descr (the (AList.lookup (op =) descr i));
+
+in
+
+fun mk_case_names_induct descr = RuleCases.case_names (induct_cases descr);
+
+fun mk_case_names_exhausts descr new =
+ map (RuleCases.case_names o exhaust_cases descr o #1)
+ (filter (fn ((_, (name, _, _))) => member (op =) new name) descr);
+
+end;
+
+fun add_rules simps case_thms rec_thms inject distinct
+ weak_case_congs cong_att =
+ PureThy.add_thmss [((Binding.name "simps", simps), []),
+ ((Binding.empty, flat case_thms @
+ flat distinct @ rec_thms), [Simplifier.simp_add]),
+ ((Binding.empty, rec_thms), [Code.add_default_eqn_attribute]),
+ ((Binding.empty, flat inject), [iff_add]),
+ ((Binding.empty, map (fn th => th RS notE) (flat distinct)), [Classical.safe_elim NONE]),
+ ((Binding.empty, weak_case_congs), [cong_att])]
+ #> snd;
+
+
+(* add_cases_induct *)
+
+fun add_cases_induct infos induction thy =
+ let
+ val inducts = ProjectRule.projections (ProofContext.init thy) induction;
+
+ fun named_rules (name, {index, exhaustion, ...}: datatype_info) =
+ [((Binding.empty, nth inducts index), [Induct.induct_type name]),
+ ((Binding.empty, exhaustion), [Induct.cases_type name])];
+ fun unnamed_rule i =
+ ((Binding.empty, nth inducts i), [Thm.kind_internal, Induct.induct_type ""]);
+ in
+ thy |> PureThy.add_thms
+ (maps named_rules infos @
+ map unnamed_rule (length infos upto length inducts - 1)) |> snd
+ |> PureThy.add_thmss [((Binding.name "inducts", inducts), [])] |> snd
+ end;
+
+
+
+(**** simplification procedure for showing distinctness of constructors ****)
+
+fun stripT (i, Type ("fun", [_, T])) = stripT (i + 1, T)
+ | stripT p = p;
+
+fun stripC (i, f $ x) = stripC (i + 1, f)
+ | stripC p = p;
+
+val distinctN = "constr_distinct";
+
+fun distinct_rule thy ss tname eq_t = case #distinct (the_datatype thy tname) of
+ FewConstrs thms => Goal.prove (Simplifier.the_context ss) [] [] eq_t (K
+ (EVERY [rtac eq_reflection 1, rtac iffI 1, rtac notE 1,
+ atac 2, resolve_tac thms 1, etac FalseE 1]))
+ | ManyConstrs (thm, simpset) =>
+ let
+ val [In0_inject, In1_inject, In0_not_In1, In1_not_In0] =
+ map (PureThy.get_thm (ThyInfo.the_theory "Datatype" thy))
+ ["In0_inject", "In1_inject", "In0_not_In1", "In1_not_In0"];
+ in
+ Goal.prove (Simplifier.the_context ss) [] [] eq_t (K
+ (EVERY [rtac eq_reflection 1, rtac iffI 1, dtac thm 1,
+ full_simp_tac (Simplifier.inherit_context ss simpset) 1,
+ REPEAT (dresolve_tac [In0_inject, In1_inject] 1),
+ eresolve_tac [In0_not_In1 RS notE, In1_not_In0 RS notE] 1,
+ etac FalseE 1]))
+ end;
+
+fun distinct_proc thy ss (t as Const ("op =", _) $ t1 $ t2) =
+ (case (stripC (0, t1), stripC (0, t2)) of
+ ((i, Const (cname1, T1)), (j, Const (cname2, T2))) =>
+ (case (stripT (0, T1), stripT (0, T2)) of
+ ((i', Type (tname1, _)), (j', Type (tname2, _))) =>
+ if tname1 = tname2 andalso not (cname1 = cname2) andalso i = i' andalso j = j' then
+ (case (get_datatype_descr thy) tname1 of
+ SOME (_, (_, constrs)) => let val cnames = map fst constrs
+ in if cname1 mem cnames andalso cname2 mem cnames then
+ SOME (distinct_rule thy ss tname1
+ (Logic.mk_equals (t, Const ("False", HOLogic.boolT))))
+ else NONE
+ end
+ | NONE => NONE)
+ else NONE
+ | _ => NONE)
+ | _ => NONE)
+ | distinct_proc _ _ _ = NONE;
+
+val distinct_simproc =
+ Simplifier.simproc @{theory HOL} distinctN ["s = t"] distinct_proc;
+
+val dist_ss = HOL_ss addsimprocs [distinct_simproc];
+
+val simproc_setup =
+ Simplifier.map_simpset (fn ss => ss addsimprocs [distinct_simproc]);
+
+
+(**** translation rules for case ****)
+
+fun make_case ctxt = DatatypeCase.make_case
+ (datatype_of_constr (ProofContext.theory_of ctxt)) ctxt;
+
+fun strip_case ctxt = DatatypeCase.strip_case
+ (datatype_of_case (ProofContext.theory_of ctxt));
+
+fun add_case_tr' case_names thy =
+ Sign.add_advanced_trfuns ([], [],
+ map (fn case_name =>
+ let val case_name' = Sign.const_syntax_name thy case_name
+ in (case_name', DatatypeCase.case_tr' datatype_of_case case_name')
+ end) case_names, []) thy;
+
+val trfun_setup =
+ Sign.add_advanced_trfuns ([],
+ [("_case_syntax", DatatypeCase.case_tr true datatype_of_constr)],
+ [], []);
+
+
+(* prepare types *)
+
+fun read_typ thy ((Ts, sorts), str) =
+ let
+ val ctxt = ProofContext.init thy
+ |> fold (Variable.declare_typ o TFree) sorts;
+ val T = Syntax.read_typ ctxt str;
+ in (Ts @ [T], Term.add_tfreesT T sorts) end;
+
+fun cert_typ sign ((Ts, sorts), raw_T) =
+ let
+ val T = Type.no_tvars (Sign.certify_typ sign raw_T) handle
+ TYPE (msg, _, _) => error msg;
+ val sorts' = Term.add_tfreesT T sorts;
+ in (Ts @ [T],
+ case duplicates (op =) (map fst sorts') of
+ [] => sorts'
+ | dups => error ("Inconsistent sort constraints for " ^ commas dups))
+ end;
+
+
+(**** make datatype info ****)
+
+fun make_dt_info alt_names descr sorts induct reccomb_names rec_thms
+ (((((((((i, (_, (tname, _, _))), case_name), case_thms),
+ exhaustion_thm), distinct_thm), inject), nchotomy), case_cong), weak_case_cong) =
+ (tname,
+ {index = i,
+ alt_names = alt_names,
+ descr = descr,
+ sorts = sorts,
+ rec_names = reccomb_names,
+ rec_rewrites = rec_thms,
+ case_name = case_name,
+ case_rewrites = case_thms,
+ induction = induct,
+ exhaustion = exhaustion_thm,
+ distinct = distinct_thm,
+ inject = inject,
+ nchotomy = nchotomy,
+ case_cong = case_cong,
+ weak_case_cong = weak_case_cong});
+
+type rules = {distinct : thm list list,
+ inject : thm list list,
+ exhaustion : thm list,
+ rec_thms : thm list,
+ case_thms : thm list list,
+ split_thms : (thm * thm) list,
+ induction : thm,
+ simps : thm list}
+
+structure DatatypeInterpretation = InterpretationFun
+ (type T = datatype_config * string list val eq: T * T -> bool = eq_snd op =);
+fun interpretation f = DatatypeInterpretation.interpretation (uncurry f);
+
+
+(******************* definitional introduction of datatypes *******************)
+
+fun add_datatype_def (config : datatype_config) new_type_names descr sorts types_syntax constr_syntax dt_info
+ case_names_induct case_names_exhausts thy =
+ let
+ val _ = message config ("Proofs for datatype(s) " ^ commas_quote new_type_names);
+
+ val ((inject, distinct, dist_rewrites, simproc_dists, induct), thy2) = thy |>
+ DatatypeRepProofs.representation_proofs config dt_info new_type_names descr sorts
+ types_syntax constr_syntax case_names_induct;
+
+ val (casedist_thms, thy3) = DatatypeAbsProofs.prove_casedist_thms config new_type_names descr
+ sorts induct case_names_exhausts thy2;
+ val ((reccomb_names, rec_thms), thy4) = DatatypeAbsProofs.prove_primrec_thms
+ config new_type_names descr sorts dt_info inject dist_rewrites
+ (Simplifier.theory_context thy3 dist_ss) induct thy3;
+ val ((case_thms, case_names), thy6) = DatatypeAbsProofs.prove_case_thms
+ config new_type_names descr sorts reccomb_names rec_thms thy4;
+ val (split_thms, thy7) = DatatypeAbsProofs.prove_split_thms config new_type_names
+ descr sorts inject dist_rewrites casedist_thms case_thms thy6;
+ val (nchotomys, thy8) = DatatypeAbsProofs.prove_nchotomys config new_type_names
+ descr sorts casedist_thms thy7;
+ val (case_congs, thy9) = DatatypeAbsProofs.prove_case_congs new_type_names
+ descr sorts nchotomys case_thms thy8;
+ val (weak_case_congs, thy10) = DatatypeAbsProofs.prove_weak_case_congs new_type_names
+ descr sorts thy9;
+
+ val dt_infos = map
+ (make_dt_info (SOME new_type_names) (flat descr) sorts induct reccomb_names rec_thms)
+ ((0 upto length (hd descr) - 1) ~~ (hd descr) ~~ case_names ~~ case_thms ~~
+ casedist_thms ~~ simproc_dists ~~ inject ~~ nchotomys ~~ case_congs ~~ weak_case_congs);
+
+ val simps = flat (distinct @ inject @ case_thms) @ rec_thms;
+
+ val thy12 =
+ thy10
+ |> add_case_tr' case_names
+ |> Sign.add_path (space_implode "_" new_type_names)
+ |> add_rules simps case_thms rec_thms inject distinct
+ weak_case_congs (Simplifier.attrib (op addcongs))
+ |> put_dt_infos dt_infos
+ |> add_cases_induct dt_infos induct
+ |> Sign.parent_path
+ |> store_thmss "splits" new_type_names (map (fn (x, y) => [x, y]) split_thms) |> snd
+ |> DatatypeInterpretation.data (config, map fst dt_infos);
+ in
+ ({distinct = distinct,
+ inject = inject,
+ exhaustion = casedist_thms,
+ rec_thms = rec_thms,
+ case_thms = case_thms,
+ split_thms = split_thms,
+ induction = induct,
+ simps = simps}, thy12)
+ end;
+
+
+(*********************** declare existing type as datatype *********************)
+
+fun prove_rep_datatype (config : datatype_config) alt_names new_type_names descr sorts induct inject half_distinct thy =
+ let
+ val ((_, [induct']), _) =
+ Variable.importT_thms [induct] (Variable.thm_context induct);
+
+ fun err t = error ("Ill-formed predicate in induction rule: " ^
+ Syntax.string_of_term_global thy t);
+
+ fun get_typ (t as _ $ Var (_, Type (tname, Ts))) =
+ ((tname, map (fst o dest_TFree) Ts) handle TERM _ => err t)
+ | get_typ t = err t;
+ val dtnames = map get_typ (HOLogic.dest_conj (HOLogic.dest_Trueprop (Thm.concl_of induct')));
+
+ val dt_info = get_datatypes thy;
+
+ val distinct = (map o maps) (fn thm => [thm, thm RS not_sym]) half_distinct;
+ val (case_names_induct, case_names_exhausts) =
+ (mk_case_names_induct descr, mk_case_names_exhausts descr (map #1 dtnames));
+
+ val _ = message config ("Proofs for datatype(s) " ^ commas_quote new_type_names);
+
+ val (casedist_thms, thy2) = thy |>
+ DatatypeAbsProofs.prove_casedist_thms config new_type_names [descr] sorts induct
+ case_names_exhausts;
+ val ((reccomb_names, rec_thms), thy3) = DatatypeAbsProofs.prove_primrec_thms
+ config new_type_names [descr] sorts dt_info inject distinct
+ (Simplifier.theory_context thy2 dist_ss) induct thy2;
+ val ((case_thms, case_names), thy4) = DatatypeAbsProofs.prove_case_thms
+ config new_type_names [descr] sorts reccomb_names rec_thms thy3;
+ val (split_thms, thy5) = DatatypeAbsProofs.prove_split_thms
+ config new_type_names [descr] sorts inject distinct casedist_thms case_thms thy4;
+ val (nchotomys, thy6) = DatatypeAbsProofs.prove_nchotomys config new_type_names
+ [descr] sorts casedist_thms thy5;
+ val (case_congs, thy7) = DatatypeAbsProofs.prove_case_congs new_type_names
+ [descr] sorts nchotomys case_thms thy6;
+ val (weak_case_congs, thy8) = DatatypeAbsProofs.prove_weak_case_congs new_type_names
+ [descr] sorts thy7;
+
+ val ((_, [induct']), thy10) =
+ thy8
+ |> store_thmss "inject" new_type_names inject
+ ||>> store_thmss "distinct" new_type_names distinct
+ ||> Sign.add_path (space_implode "_" new_type_names)
+ ||>> PureThy.add_thms [((Binding.name "induct", induct), [case_names_induct])];
+
+ val dt_infos = map (make_dt_info alt_names descr sorts induct' reccomb_names rec_thms)
+ ((0 upto length descr - 1) ~~ descr ~~ case_names ~~ case_thms ~~ casedist_thms ~~
+ map FewConstrs distinct ~~ inject ~~ nchotomys ~~ case_congs ~~ weak_case_congs);
+
+ val simps = flat (distinct @ inject @ case_thms) @ rec_thms;
+
+ val thy11 =
+ thy10
+ |> add_case_tr' case_names
+ |> add_rules simps case_thms rec_thms inject distinct
+ weak_case_congs (Simplifier.attrib (op addcongs))
+ |> put_dt_infos dt_infos
+ |> add_cases_induct dt_infos induct'
+ |> Sign.parent_path
+ |> store_thmss "splits" new_type_names (map (fn (x, y) => [x, y]) split_thms)
+ |> snd
+ |> DatatypeInterpretation.data (config, map fst dt_infos);
+ in
+ ({distinct = distinct,
+ inject = inject,
+ exhaustion = casedist_thms,
+ rec_thms = rec_thms,
+ case_thms = case_thms,
+ split_thms = split_thms,
+ induction = induct',
+ simps = simps}, thy11)
+ end;
+
+fun gen_rep_datatype prep_term (config : datatype_config) after_qed alt_names raw_ts thy =
+ let
+ fun constr_of_term (Const (c, T)) = (c, T)
+ | constr_of_term t =
+ error ("Not a constant: " ^ Syntax.string_of_term_global thy t);
+ fun no_constr (c, T) = error ("Bad constructor: "
+ ^ Sign.extern_const thy c ^ "::"
+ ^ Syntax.string_of_typ_global thy T);
+ fun type_of_constr (cT as (_, T)) =
+ let
+ val frees = OldTerm.typ_tfrees T;
+ val (tyco, vs) = ((apsnd o map) (dest_TFree) o dest_Type o snd o strip_type) T
+ handle TYPE _ => no_constr cT
+ val _ = if has_duplicates (eq_fst (op =)) vs then no_constr cT else ();
+ val _ = if length frees <> length vs then no_constr cT else ();
+ in (tyco, (vs, cT)) end;
+
+ val raw_cs = AList.group (op =) (map (type_of_constr o constr_of_term o prep_term thy) raw_ts);
+ val _ = case map_filter (fn (tyco, _) =>
+ if Symtab.defined (get_datatypes thy) tyco then SOME tyco else NONE) raw_cs
+ of [] => ()
+ | tycos => error ("Type(s) " ^ commas (map quote tycos)
+ ^ " already represented inductivly");
+ val raw_vss = maps (map (map snd o fst) o snd) raw_cs;
+ val ms = case distinct (op =) (map length raw_vss)
+ of [n] => 0 upto n - 1
+ | _ => error ("Different types in given constructors");
+ fun inter_sort m = map (fn xs => nth xs m) raw_vss
+ |> Library.foldr1 (Sorts.inter_sort (Sign.classes_of thy))
+ val sorts = map inter_sort ms;
+ val vs = Name.names Name.context Name.aT sorts;
+
+ fun norm_constr (raw_vs, (c, T)) = (c, map_atyps
+ (TFree o (the o AList.lookup (op =) (map fst raw_vs ~~ vs)) o fst o dest_TFree) T);
+
+ val cs = map (apsnd (map norm_constr)) raw_cs;
+ val dtyps_of_typ = map (dtyp_of_typ (map (rpair (map fst vs) o fst) cs))
+ o fst o strip_type;
+ val new_type_names = map Long_Name.base_name (the_default (map fst cs) alt_names);
+
+ fun mk_spec (i, (tyco, constr)) = (i, (tyco,
+ map (DtTFree o fst) vs,
+ (map o apsnd) dtyps_of_typ constr))
+ val descr = map_index mk_spec cs;
+ val injs = DatatypeProp.make_injs [descr] vs;
+ val half_distincts = map snd (DatatypeProp.make_distincts [descr] vs);
+ val ind = DatatypeProp.make_ind [descr] vs;
+ val rules = (map o map o map) Logic.close_form [[[ind]], injs, half_distincts];
+
+ fun after_qed' raw_thms =
+ let
+ val [[[induct]], injs, half_distincts] =
+ unflat rules (map Drule.zero_var_indexes_list raw_thms);
+ (*FIXME somehow dubious*)
+ in
+ ProofContext.theory_result
+ (prove_rep_datatype config alt_names new_type_names descr vs induct injs half_distincts)
+ #-> after_qed
+ end;
+ in
+ thy
+ |> ProofContext.init
+ |> Proof.theorem_i NONE after_qed' ((map o map) (rpair []) (flat rules))
+ end;
+
+val rep_datatype = gen_rep_datatype Sign.cert_term;
+val rep_datatype_cmd = gen_rep_datatype Syntax.read_term_global default_datatype_config (K I);
+
+
+
+(******************************** add datatype ********************************)
+
+fun gen_add_datatype prep_typ (config : datatype_config) new_type_names dts thy =
+ let
+ val _ = Theory.requires thy "Datatype" "datatype definitions";
+
+ (* this theory is used just for parsing *)
+
+ val tmp_thy = thy |>
+ Theory.copy |>
+ Sign.add_types (map (fn (tvs, tname, mx, _) =>
+ (tname, length tvs, mx)) dts);
+
+ val (tyvars, _, _, _)::_ = dts;
+ val (new_dts, types_syntax) = ListPair.unzip (map (fn (tvs, tname, mx, _) =>
+ let val full_tname = Sign.full_name tmp_thy (Binding.map_name (Syntax.type_name mx) tname)
+ in (case duplicates (op =) tvs of
+ [] => if eq_set (tyvars, tvs) then ((full_tname, tvs), (tname, mx))
+ else error ("Mutually recursive datatypes must have same type parameters")
+ | dups => error ("Duplicate parameter(s) for datatype " ^ quote (Binding.str_of tname) ^
+ " : " ^ commas dups))
+ end) dts);
+
+ val _ = (case duplicates (op =) (map fst new_dts) @ duplicates (op =) new_type_names of
+ [] => () | dups => error ("Duplicate datatypes: " ^ commas dups));
+
+ fun prep_dt_spec ((tvs, tname, mx, constrs), tname') (dts', constr_syntax, sorts, i) =
+ let
+ fun prep_constr (cname, cargs, mx') (constrs, constr_syntax', sorts') =
+ let
+ val (cargs', sorts'') = Library.foldl (prep_typ tmp_thy) (([], sorts'), cargs);
+ val _ = (case fold (curry OldTerm.add_typ_tfree_names) cargs' [] \\ tvs of
+ [] => ()
+ | vs => error ("Extra type variables on rhs: " ^ commas vs))
+ in (constrs @ [((if #flat_names config then Sign.full_name tmp_thy else
+ Sign.full_name_path tmp_thy tname')
+ (Binding.map_name (Syntax.const_name mx') cname),
+ map (dtyp_of_typ new_dts) cargs')],
+ constr_syntax' @ [(cname, mx')], sorts'')
+ end handle ERROR msg => cat_error msg
+ ("The error above occured in constructor " ^ quote (Binding.str_of cname) ^
+ " of datatype " ^ quote (Binding.str_of tname));
+
+ val (constrs', constr_syntax', sorts') =
+ fold prep_constr constrs ([], [], sorts)
+
+ in
+ case duplicates (op =) (map fst constrs') of
+ [] =>
+ (dts' @ [(i, (Sign.full_name tmp_thy (Binding.map_name (Syntax.type_name mx) tname),
+ map DtTFree tvs, constrs'))],
+ constr_syntax @ [constr_syntax'], sorts', i + 1)
+ | dups => error ("Duplicate constructors " ^ commas dups ^
+ " in datatype " ^ quote (Binding.str_of tname))
+ end;
+
+ val (dts', constr_syntax, sorts', i) =
+ fold prep_dt_spec (dts ~~ new_type_names) ([], [], [], 0);
+ val sorts = sorts' @ (map (rpair (Sign.defaultS tmp_thy)) (tyvars \\ map fst sorts'));
+ val dt_info = get_datatypes thy;
+ val (descr, _) = unfold_datatypes tmp_thy dts' sorts dt_info dts' i;
+ val _ = check_nonempty descr handle (exn as Datatype_Empty s) =>
+ if #strict config then error ("Nonemptiness check failed for datatype " ^ s)
+ else raise exn;
+
+ val descr' = flat descr;
+ val case_names_induct = mk_case_names_induct descr';
+ val case_names_exhausts = mk_case_names_exhausts descr' (map #1 new_dts);
+ in
+ add_datatype_def
+ (config : datatype_config) new_type_names descr sorts types_syntax constr_syntax dt_info
+ case_names_induct case_names_exhausts thy
+ end;
+
+val add_datatype = gen_add_datatype cert_typ;
+val add_datatype_cmd = gen_add_datatype read_typ default_datatype_config;
+
+
+
+(** package setup **)
+
+(* setup theory *)
+
+val setup =
+ DatatypeRepProofs.distinctness_limit_setup #>
+ simproc_setup #>
+ trfun_setup #>
+ DatatypeInterpretation.init;
+
+
+(* outer syntax *)
+
+local structure P = OuterParse and K = OuterKeyword in
+
+val datatype_decl =
+ Scan.option (P.$$$ "(" |-- P.name --| P.$$$ ")") -- P.type_args -- P.binding -- P.opt_infix --
+ (P.$$$ "=" |-- P.enum1 "|" (P.binding -- Scan.repeat P.typ -- P.opt_mixfix));
+
+fun mk_datatype args =
+ let
+ val names = map
+ (fn ((((NONE, _), t), _), _) => Binding.name_of t | ((((SOME t, _), _), _), _) => t) args;
+ val specs = map (fn ((((_, vs), t), mx), cons) =>
+ (vs, t, mx, map (fn ((x, y), z) => (x, y, z)) cons)) args;
+ in snd o add_datatype_cmd names specs end;
+
+val _ =
+ OuterSyntax.command "datatype" "define inductive datatypes" K.thy_decl
+ (P.and_list1 datatype_decl >> (Toplevel.theory o mk_datatype));
+
+val _ =
+ OuterSyntax.command "rep_datatype" "represent existing types inductively" K.thy_goal
+ (Scan.option (P.$$$ "(" |-- Scan.repeat1 P.name --| P.$$$ ")") -- Scan.repeat1 P.term
+ >> (fn (alt_names, ts) => Toplevel.print
+ o Toplevel.theory_to_proof (rep_datatype_cmd alt_names ts)));
+
+end;
+
+
+(* document antiquotation *)
+
+val _ = ThyOutput.antiquotation "datatype" Args.tyname
+ (fn {source = src, context = ctxt, ...} => fn dtco =>
+ let
+ val thy = ProofContext.theory_of ctxt;
+ val (vs, cos) = the_datatype_spec thy dtco;
+ val ty = Type (dtco, map TFree vs);
+ fun pretty_typ_bracket (ty as Type (_, _ :: _)) =
+ Pretty.enclose "(" ")" [Syntax.pretty_typ ctxt ty]
+ | pretty_typ_bracket ty =
+ Syntax.pretty_typ ctxt ty;
+ fun pretty_constr (co, tys) =
+ (Pretty.block o Pretty.breaks)
+ (Syntax.pretty_term ctxt (Const (co, tys ---> ty)) ::
+ map pretty_typ_bracket tys);
+ val pretty_datatype =
+ Pretty.block
+ (Pretty.command "datatype" :: Pretty.brk 1 ::
+ Syntax.pretty_typ ctxt ty ::
+ Pretty.str " =" :: Pretty.brk 1 ::
+ flat (separate [Pretty.brk 1, Pretty.str "| "]
+ (map (single o pretty_constr) cos)));
+ in ThyOutput.output (ThyOutput.maybe_pretty_source (K pretty_datatype) src [()]) end);
+
+end;
+
--- a/src/HOL/Tools/datatype_package/datatype_abs_proofs.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/datatype_package/datatype_abs_proofs.ML Fri Jun 19 21:08:07 2009 +0200
@@ -155,7 +155,7 @@
(([], 0), descr' ~~ recTs ~~ rec_sets');
val ({intrs = rec_intrs, elims = rec_elims, ...}, thy1) =
- InductivePackage.add_inductive_global (serial_string ())
+ Inductive.add_inductive_global (serial_string ())
{quiet_mode = #quiet config, verbose = false, kind = Thm.internalK,
alt_name = Binding.name big_rec_name', coind = false, no_elim = false, no_ind = true,
skip_mono = true, fork_mono = false}
--- a/src/HOL/Tools/datatype_package/datatype_codegen.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/datatype_package/datatype_codegen.ML Fri Jun 19 21:08:07 2009 +0200
@@ -276,12 +276,12 @@
fun datatype_codegen thy defs dep module brack t gr = (case strip_comb t of
(c as Const (s, T), ts) =>
- (case DatatypePackage.datatype_of_case thy s of
+ (case Datatype.datatype_of_case thy s of
SOME {index, descr, ...} =>
if is_some (get_assoc_code thy (s, T)) then NONE else
SOME (pretty_case thy defs dep module brack
(#3 (the (AList.lookup op = descr index))) c ts gr )
- | NONE => case (DatatypePackage.datatype_of_constr thy s, strip_type T) of
+ | NONE => case (Datatype.datatype_of_constr thy s, strip_type T) of
(SOME {index, descr, ...}, (_, U as Type (tyname, _))) =>
if is_some (get_assoc_code thy (s, T)) then NONE else
let
@@ -296,7 +296,7 @@
| _ => NONE);
fun datatype_tycodegen thy defs dep module brack (Type (s, Ts)) gr =
- (case DatatypePackage.get_datatype thy s of
+ (case Datatype.get_datatype thy s of
NONE => NONE
| SOME {descr, sorts, ...} =>
if is_some (get_assoc_type thy s) then NONE else
@@ -331,7 +331,7 @@
fun mk_case_cert thy tyco =
let
val raw_thms =
- (#case_rewrites o DatatypePackage.the_datatype thy) tyco;
+ (#case_rewrites o Datatype.the_datatype thy) tyco;
val thms as hd_thm :: _ = raw_thms
|> Conjunction.intr_balanced
|> Thm.unvarify
@@ -364,8 +364,8 @@
fun mk_eq_eqns thy dtco =
let
- val (vs, cos) = DatatypePackage.the_datatype_spec thy dtco;
- val { descr, index, inject = inject_thms, ... } = DatatypePackage.the_datatype thy dtco;
+ val (vs, cos) = Datatype.the_datatype_spec thy dtco;
+ val { descr, index, inject = inject_thms, ... } = Datatype.the_datatype thy dtco;
val ty = Type (dtco, map TFree vs);
fun mk_eq (t1, t2) = Const (@{const_name eq_class.eq}, ty --> ty --> HOLogic.boolT)
$ t1 $ t2;
@@ -383,7 +383,7 @@
val refl = HOLogic.mk_Trueprop (true_eq (Free ("x", ty), Free ("x", ty)));
val simpset = Simplifier.context (ProofContext.init thy) (HOL_basic_ss
addsimps (map Simpdata.mk_eq (@{thm eq} :: @{thm eq_True} :: inject_thms))
- addsimprocs [DatatypePackage.distinct_simproc]);
+ addsimprocs [Datatype.distinct_simproc]);
fun prove prop = SkipProof.prove_global thy [] [] prop (K (ALLGOALS (simp_tac simpset)))
|> Simpdata.mk_eq;
in map (rpair true o prove) (triv_injects @ injects @ distincts) @ [(prove refl, false)] end;
@@ -428,11 +428,11 @@
fun add_all_code config dtcos thy =
let
- val (vs :: _, coss) = (split_list o map (DatatypePackage.the_datatype_spec thy)) dtcos;
+ val (vs :: _, coss) = (split_list o map (Datatype.the_datatype_spec thy)) dtcos;
val any_css = map2 (mk_constr_consts thy vs) dtcos coss;
val css = if exists is_none any_css then []
else map_filter I any_css;
- val case_rewrites = maps (#case_rewrites o DatatypePackage.the_datatype thy) dtcos;
+ val case_rewrites = maps (#case_rewrites o Datatype.the_datatype thy) dtcos;
val certs = map (mk_case_cert thy) dtcos;
in
if null css then thy
@@ -450,6 +450,6 @@
val setup =
add_codegen "datatype" datatype_codegen
#> add_tycodegen "datatype" datatype_tycodegen
- #> DatatypePackage.interpretation add_all_code
+ #> Datatype.interpretation add_all_code
end;
--- a/src/HOL/Tools/datatype_package/datatype_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,705 +0,0 @@
-(* Title: HOL/Tools/datatype_package.ML
- Author: Stefan Berghofer, TU Muenchen
-
-Datatype package for Isabelle/HOL.
-*)
-
-signature DATATYPE_PACKAGE =
-sig
- type datatype_config = DatatypeAux.datatype_config
- type datatype_info = DatatypeAux.datatype_info
- type descr = DatatypeAux.descr
- val get_datatypes : theory -> datatype_info Symtab.table
- val get_datatype : theory -> string -> datatype_info option
- val the_datatype : theory -> string -> datatype_info
- val datatype_of_constr : theory -> string -> datatype_info option
- val datatype_of_case : theory -> string -> datatype_info option
- val the_datatype_spec : theory -> string -> (string * sort) list * (string * typ list) list
- val the_datatype_descr : theory -> string list
- -> descr * (string * sort) list * string list
- * (string list * string list) * (typ list * typ list)
- val get_datatype_constrs : theory -> string -> (string * typ) list option
- val distinct_simproc : simproc
- val make_case : Proof.context -> bool -> string list -> term ->
- (term * term) list -> term * (term * (int * bool)) list
- val strip_case : Proof.context -> bool -> term -> (term * (term * term) list) option
- val read_typ: theory ->
- (typ list * (string * sort) list) * string -> typ list * (string * sort) list
- val interpretation : (datatype_config -> string list -> theory -> theory) -> theory -> theory
- type rules = {distinct : thm list list,
- inject : thm list list,
- exhaustion : thm list,
- rec_thms : thm list,
- case_thms : thm list list,
- split_thms : (thm * thm) list,
- induction : thm,
- simps : thm list}
- val rep_datatype : datatype_config -> (rules -> Proof.context -> Proof.context)
- -> string list option -> term list -> theory -> Proof.state;
- val rep_datatype_cmd : string list option -> string list -> theory -> Proof.state
- val add_datatype : datatype_config -> string list -> (string list * binding * mixfix *
- (binding * typ list * mixfix) list) list -> theory -> rules * theory
- val add_datatype_cmd : string list -> (string list * binding * mixfix *
- (binding * string list * mixfix) list) list -> theory -> rules * theory
- val setup: theory -> theory
- val print_datatypes : theory -> unit
-end;
-
-structure DatatypePackage : DATATYPE_PACKAGE =
-struct
-
-open DatatypeAux;
-
-
-(* theory data *)
-
-structure DatatypesData = TheoryDataFun
-(
- type T =
- {types: datatype_info Symtab.table,
- constrs: datatype_info Symtab.table,
- cases: datatype_info Symtab.table};
-
- val empty =
- {types = Symtab.empty, constrs = Symtab.empty, cases = Symtab.empty};
- val copy = I;
- val extend = I;
- fun merge _
- ({types = types1, constrs = constrs1, cases = cases1},
- {types = types2, constrs = constrs2, cases = cases2}) =
- {types = Symtab.merge (K true) (types1, types2),
- constrs = Symtab.merge (K true) (constrs1, constrs2),
- cases = Symtab.merge (K true) (cases1, cases2)};
-);
-
-val get_datatypes = #types o DatatypesData.get;
-val map_datatypes = DatatypesData.map;
-
-fun print_datatypes thy =
- Pretty.writeln (Pretty.strs ("datatypes:" ::
- map #1 (NameSpace.extern_table (Sign.type_space thy, get_datatypes thy))));
-
-
-(** theory information about datatypes **)
-
-fun put_dt_infos (dt_infos : (string * datatype_info) list) =
- map_datatypes (fn {types, constrs, cases} =>
- {types = fold Symtab.update dt_infos types,
- constrs = fold Symtab.default (*conservative wrt. overloaded constructors*)
- (maps (fn (_, info as {descr, index, ...}) => map (rpair info o fst)
- (#3 (the (AList.lookup op = descr index)))) dt_infos) constrs,
- cases = fold Symtab.update
- (map (fn (_, info as {case_name, ...}) => (case_name, info)) dt_infos)
- cases});
-
-val get_datatype = Symtab.lookup o get_datatypes;
-
-fun the_datatype thy name = (case get_datatype thy name of
- SOME info => info
- | NONE => error ("Unknown datatype " ^ quote name));
-
-val datatype_of_constr = Symtab.lookup o #constrs o DatatypesData.get;
-val datatype_of_case = Symtab.lookup o #cases o DatatypesData.get;
-
-fun get_datatype_descr thy dtco =
- get_datatype thy dtco
- |> Option.map (fn info as { descr, index, ... } =>
- (info, (((fn SOME (_, dtys, cos) => (dtys, cos)) o AList.lookup (op =) descr) index)));
-
-fun the_datatype_spec thy dtco =
- let
- val info as { descr, index, sorts = raw_sorts, ... } = the_datatype thy dtco;
- val SOME (_, dtys, raw_cos) = AList.lookup (op =) descr index;
- val sorts = map ((fn v => (v, (the o AList.lookup (op =) raw_sorts) v))
- o DatatypeAux.dest_DtTFree) dtys;
- val cos = map
- (fn (co, tys) => (co, map (DatatypeAux.typ_of_dtyp descr sorts) tys)) raw_cos;
- in (sorts, cos) end;
-
-fun the_datatype_descr thy (raw_tycos as raw_tyco :: _) =
- let
- val info = the_datatype thy raw_tyco;
- val descr = #descr info;
-
- val SOME (_, dtys, raw_cos) = AList.lookup (op =) descr (#index info);
- val vs = map ((fn v => (v, (the o AList.lookup (op =) (#sorts info)) v))
- o dest_DtTFree) dtys;
-
- fun is_DtTFree (DtTFree _) = true
- | is_DtTFree _ = false
- val k = find_index (fn (_, (_, dTs, _)) => not (forall is_DtTFree dTs)) descr;
- val protoTs as (dataTs, _) = chop k descr
- |> (pairself o map) (fn (_, (tyco, dTs, _)) => (tyco, map (typ_of_dtyp descr vs) dTs));
-
- val tycos = map fst dataTs;
- val _ = if gen_eq_set (op =) (tycos, raw_tycos) then ()
- else error ("Type constructors " ^ commas (map quote raw_tycos)
- ^ "do not belong exhaustively to one mutual recursive datatype");
-
- val (Ts, Us) = (pairself o map) Type protoTs;
-
- val names = map Long_Name.base_name (the_default tycos (#alt_names info));
- val (auxnames, _) = Name.make_context names
- |> fold_map (yield_singleton Name.variants o name_of_typ) Us
-
- in (descr, vs, tycos, (names, auxnames), (Ts, Us)) end;
-
-fun get_datatype_constrs thy dtco =
- case try (the_datatype_spec thy) dtco
- of SOME (sorts, cos) =>
- let
- fun subst (v, sort) = TVar ((v, 0), sort);
- fun subst_ty (TFree v) = subst v
- | subst_ty ty = ty;
- val dty = Type (dtco, map subst sorts);
- fun mk_co (co, tys) = (co, map (Term.map_atyps subst_ty) tys ---> dty);
- in SOME (map mk_co cos) end
- | NONE => NONE;
-
-
-(** induct method setup **)
-
-(* case names *)
-
-local
-
-fun dt_recs (DtTFree _) = []
- | dt_recs (DtType (_, dts)) = maps dt_recs dts
- | dt_recs (DtRec i) = [i];
-
-fun dt_cases (descr: descr) (_, args, constrs) =
- let
- fun the_bname i = Long_Name.base_name (#1 (the (AList.lookup (op =) descr i)));
- val bnames = map the_bname (distinct (op =) (maps dt_recs args));
- in map (fn (c, _) => space_implode "_" (Long_Name.base_name c :: bnames)) constrs end;
-
-
-fun induct_cases descr =
- DatatypeProp.indexify_names (maps (dt_cases descr) (map #2 descr));
-
-fun exhaust_cases descr i = dt_cases descr (the (AList.lookup (op =) descr i));
-
-in
-
-fun mk_case_names_induct descr = RuleCases.case_names (induct_cases descr);
-
-fun mk_case_names_exhausts descr new =
- map (RuleCases.case_names o exhaust_cases descr o #1)
- (filter (fn ((_, (name, _, _))) => member (op =) new name) descr);
-
-end;
-
-fun add_rules simps case_thms rec_thms inject distinct
- weak_case_congs cong_att =
- PureThy.add_thmss [((Binding.name "simps", simps), []),
- ((Binding.empty, flat case_thms @
- flat distinct @ rec_thms), [Simplifier.simp_add]),
- ((Binding.empty, rec_thms), [Code.add_default_eqn_attribute]),
- ((Binding.empty, flat inject), [iff_add]),
- ((Binding.empty, map (fn th => th RS notE) (flat distinct)), [Classical.safe_elim NONE]),
- ((Binding.empty, weak_case_congs), [cong_att])]
- #> snd;
-
-
-(* add_cases_induct *)
-
-fun add_cases_induct infos induction thy =
- let
- val inducts = ProjectRule.projections (ProofContext.init thy) induction;
-
- fun named_rules (name, {index, exhaustion, ...}: datatype_info) =
- [((Binding.empty, nth inducts index), [Induct.induct_type name]),
- ((Binding.empty, exhaustion), [Induct.cases_type name])];
- fun unnamed_rule i =
- ((Binding.empty, nth inducts i), [Thm.kind_internal, Induct.induct_type ""]);
- in
- thy |> PureThy.add_thms
- (maps named_rules infos @
- map unnamed_rule (length infos upto length inducts - 1)) |> snd
- |> PureThy.add_thmss [((Binding.name "inducts", inducts), [])] |> snd
- end;
-
-
-
-(**** simplification procedure for showing distinctness of constructors ****)
-
-fun stripT (i, Type ("fun", [_, T])) = stripT (i + 1, T)
- | stripT p = p;
-
-fun stripC (i, f $ x) = stripC (i + 1, f)
- | stripC p = p;
-
-val distinctN = "constr_distinct";
-
-fun distinct_rule thy ss tname eq_t = case #distinct (the_datatype thy tname) of
- FewConstrs thms => Goal.prove (Simplifier.the_context ss) [] [] eq_t (K
- (EVERY [rtac eq_reflection 1, rtac iffI 1, rtac notE 1,
- atac 2, resolve_tac thms 1, etac FalseE 1]))
- | ManyConstrs (thm, simpset) =>
- let
- val [In0_inject, In1_inject, In0_not_In1, In1_not_In0] =
- map (PureThy.get_thm (ThyInfo.the_theory "Datatype" thy))
- ["In0_inject", "In1_inject", "In0_not_In1", "In1_not_In0"];
- in
- Goal.prove (Simplifier.the_context ss) [] [] eq_t (K
- (EVERY [rtac eq_reflection 1, rtac iffI 1, dtac thm 1,
- full_simp_tac (Simplifier.inherit_context ss simpset) 1,
- REPEAT (dresolve_tac [In0_inject, In1_inject] 1),
- eresolve_tac [In0_not_In1 RS notE, In1_not_In0 RS notE] 1,
- etac FalseE 1]))
- end;
-
-fun distinct_proc thy ss (t as Const ("op =", _) $ t1 $ t2) =
- (case (stripC (0, t1), stripC (0, t2)) of
- ((i, Const (cname1, T1)), (j, Const (cname2, T2))) =>
- (case (stripT (0, T1), stripT (0, T2)) of
- ((i', Type (tname1, _)), (j', Type (tname2, _))) =>
- if tname1 = tname2 andalso not (cname1 = cname2) andalso i = i' andalso j = j' then
- (case (get_datatype_descr thy) tname1 of
- SOME (_, (_, constrs)) => let val cnames = map fst constrs
- in if cname1 mem cnames andalso cname2 mem cnames then
- SOME (distinct_rule thy ss tname1
- (Logic.mk_equals (t, Const ("False", HOLogic.boolT))))
- else NONE
- end
- | NONE => NONE)
- else NONE
- | _ => NONE)
- | _ => NONE)
- | distinct_proc _ _ _ = NONE;
-
-val distinct_simproc =
- Simplifier.simproc @{theory HOL} distinctN ["s = t"] distinct_proc;
-
-val dist_ss = HOL_ss addsimprocs [distinct_simproc];
-
-val simproc_setup =
- Simplifier.map_simpset (fn ss => ss addsimprocs [distinct_simproc]);
-
-
-(**** translation rules for case ****)
-
-fun make_case ctxt = DatatypeCase.make_case
- (datatype_of_constr (ProofContext.theory_of ctxt)) ctxt;
-
-fun strip_case ctxt = DatatypeCase.strip_case
- (datatype_of_case (ProofContext.theory_of ctxt));
-
-fun add_case_tr' case_names thy =
- Sign.add_advanced_trfuns ([], [],
- map (fn case_name =>
- let val case_name' = Sign.const_syntax_name thy case_name
- in (case_name', DatatypeCase.case_tr' datatype_of_case case_name')
- end) case_names, []) thy;
-
-val trfun_setup =
- Sign.add_advanced_trfuns ([],
- [("_case_syntax", DatatypeCase.case_tr true datatype_of_constr)],
- [], []);
-
-
-(* prepare types *)
-
-fun read_typ thy ((Ts, sorts), str) =
- let
- val ctxt = ProofContext.init thy
- |> fold (Variable.declare_typ o TFree) sorts;
- val T = Syntax.read_typ ctxt str;
- in (Ts @ [T], Term.add_tfreesT T sorts) end;
-
-fun cert_typ sign ((Ts, sorts), raw_T) =
- let
- val T = Type.no_tvars (Sign.certify_typ sign raw_T) handle
- TYPE (msg, _, _) => error msg;
- val sorts' = Term.add_tfreesT T sorts;
- in (Ts @ [T],
- case duplicates (op =) (map fst sorts') of
- [] => sorts'
- | dups => error ("Inconsistent sort constraints for " ^ commas dups))
- end;
-
-
-(**** make datatype info ****)
-
-fun make_dt_info alt_names descr sorts induct reccomb_names rec_thms
- (((((((((i, (_, (tname, _, _))), case_name), case_thms),
- exhaustion_thm), distinct_thm), inject), nchotomy), case_cong), weak_case_cong) =
- (tname,
- {index = i,
- alt_names = alt_names,
- descr = descr,
- sorts = sorts,
- rec_names = reccomb_names,
- rec_rewrites = rec_thms,
- case_name = case_name,
- case_rewrites = case_thms,
- induction = induct,
- exhaustion = exhaustion_thm,
- distinct = distinct_thm,
- inject = inject,
- nchotomy = nchotomy,
- case_cong = case_cong,
- weak_case_cong = weak_case_cong});
-
-type rules = {distinct : thm list list,
- inject : thm list list,
- exhaustion : thm list,
- rec_thms : thm list,
- case_thms : thm list list,
- split_thms : (thm * thm) list,
- induction : thm,
- simps : thm list}
-
-structure DatatypeInterpretation = InterpretationFun
- (type T = datatype_config * string list val eq: T * T -> bool = eq_snd op =);
-fun interpretation f = DatatypeInterpretation.interpretation (uncurry f);
-
-
-(******************* definitional introduction of datatypes *******************)
-
-fun add_datatype_def (config : datatype_config) new_type_names descr sorts types_syntax constr_syntax dt_info
- case_names_induct case_names_exhausts thy =
- let
- val _ = message config ("Proofs for datatype(s) " ^ commas_quote new_type_names);
-
- val ((inject, distinct, dist_rewrites, simproc_dists, induct), thy2) = thy |>
- DatatypeRepProofs.representation_proofs config dt_info new_type_names descr sorts
- types_syntax constr_syntax case_names_induct;
-
- val (casedist_thms, thy3) = DatatypeAbsProofs.prove_casedist_thms config new_type_names descr
- sorts induct case_names_exhausts thy2;
- val ((reccomb_names, rec_thms), thy4) = DatatypeAbsProofs.prove_primrec_thms
- config new_type_names descr sorts dt_info inject dist_rewrites
- (Simplifier.theory_context thy3 dist_ss) induct thy3;
- val ((case_thms, case_names), thy6) = DatatypeAbsProofs.prove_case_thms
- config new_type_names descr sorts reccomb_names rec_thms thy4;
- val (split_thms, thy7) = DatatypeAbsProofs.prove_split_thms config new_type_names
- descr sorts inject dist_rewrites casedist_thms case_thms thy6;
- val (nchotomys, thy8) = DatatypeAbsProofs.prove_nchotomys config new_type_names
- descr sorts casedist_thms thy7;
- val (case_congs, thy9) = DatatypeAbsProofs.prove_case_congs new_type_names
- descr sorts nchotomys case_thms thy8;
- val (weak_case_congs, thy10) = DatatypeAbsProofs.prove_weak_case_congs new_type_names
- descr sorts thy9;
-
- val dt_infos = map
- (make_dt_info (SOME new_type_names) (flat descr) sorts induct reccomb_names rec_thms)
- ((0 upto length (hd descr) - 1) ~~ (hd descr) ~~ case_names ~~ case_thms ~~
- casedist_thms ~~ simproc_dists ~~ inject ~~ nchotomys ~~ case_congs ~~ weak_case_congs);
-
- val simps = flat (distinct @ inject @ case_thms) @ rec_thms;
-
- val thy12 =
- thy10
- |> add_case_tr' case_names
- |> Sign.add_path (space_implode "_" new_type_names)
- |> add_rules simps case_thms rec_thms inject distinct
- weak_case_congs (Simplifier.attrib (op addcongs))
- |> put_dt_infos dt_infos
- |> add_cases_induct dt_infos induct
- |> Sign.parent_path
- |> store_thmss "splits" new_type_names (map (fn (x, y) => [x, y]) split_thms) |> snd
- |> DatatypeInterpretation.data (config, map fst dt_infos);
- in
- ({distinct = distinct,
- inject = inject,
- exhaustion = casedist_thms,
- rec_thms = rec_thms,
- case_thms = case_thms,
- split_thms = split_thms,
- induction = induct,
- simps = simps}, thy12)
- end;
-
-
-(*********************** declare existing type as datatype *********************)
-
-fun prove_rep_datatype (config : datatype_config) alt_names new_type_names descr sorts induct inject half_distinct thy =
- let
- val ((_, [induct']), _) =
- Variable.importT_thms [induct] (Variable.thm_context induct);
-
- fun err t = error ("Ill-formed predicate in induction rule: " ^
- Syntax.string_of_term_global thy t);
-
- fun get_typ (t as _ $ Var (_, Type (tname, Ts))) =
- ((tname, map (fst o dest_TFree) Ts) handle TERM _ => err t)
- | get_typ t = err t;
- val dtnames = map get_typ (HOLogic.dest_conj (HOLogic.dest_Trueprop (Thm.concl_of induct')));
-
- val dt_info = get_datatypes thy;
-
- val distinct = (map o maps) (fn thm => [thm, thm RS not_sym]) half_distinct;
- val (case_names_induct, case_names_exhausts) =
- (mk_case_names_induct descr, mk_case_names_exhausts descr (map #1 dtnames));
-
- val _ = message config ("Proofs for datatype(s) " ^ commas_quote new_type_names);
-
- val (casedist_thms, thy2) = thy |>
- DatatypeAbsProofs.prove_casedist_thms config new_type_names [descr] sorts induct
- case_names_exhausts;
- val ((reccomb_names, rec_thms), thy3) = DatatypeAbsProofs.prove_primrec_thms
- config new_type_names [descr] sorts dt_info inject distinct
- (Simplifier.theory_context thy2 dist_ss) induct thy2;
- val ((case_thms, case_names), thy4) = DatatypeAbsProofs.prove_case_thms
- config new_type_names [descr] sorts reccomb_names rec_thms thy3;
- val (split_thms, thy5) = DatatypeAbsProofs.prove_split_thms
- config new_type_names [descr] sorts inject distinct casedist_thms case_thms thy4;
- val (nchotomys, thy6) = DatatypeAbsProofs.prove_nchotomys config new_type_names
- [descr] sorts casedist_thms thy5;
- val (case_congs, thy7) = DatatypeAbsProofs.prove_case_congs new_type_names
- [descr] sorts nchotomys case_thms thy6;
- val (weak_case_congs, thy8) = DatatypeAbsProofs.prove_weak_case_congs new_type_names
- [descr] sorts thy7;
-
- val ((_, [induct']), thy10) =
- thy8
- |> store_thmss "inject" new_type_names inject
- ||>> store_thmss "distinct" new_type_names distinct
- ||> Sign.add_path (space_implode "_" new_type_names)
- ||>> PureThy.add_thms [((Binding.name "induct", induct), [case_names_induct])];
-
- val dt_infos = map (make_dt_info alt_names descr sorts induct' reccomb_names rec_thms)
- ((0 upto length descr - 1) ~~ descr ~~ case_names ~~ case_thms ~~ casedist_thms ~~
- map FewConstrs distinct ~~ inject ~~ nchotomys ~~ case_congs ~~ weak_case_congs);
-
- val simps = flat (distinct @ inject @ case_thms) @ rec_thms;
-
- val thy11 =
- thy10
- |> add_case_tr' case_names
- |> add_rules simps case_thms rec_thms inject distinct
- weak_case_congs (Simplifier.attrib (op addcongs))
- |> put_dt_infos dt_infos
- |> add_cases_induct dt_infos induct'
- |> Sign.parent_path
- |> store_thmss "splits" new_type_names (map (fn (x, y) => [x, y]) split_thms)
- |> snd
- |> DatatypeInterpretation.data (config, map fst dt_infos);
- in
- ({distinct = distinct,
- inject = inject,
- exhaustion = casedist_thms,
- rec_thms = rec_thms,
- case_thms = case_thms,
- split_thms = split_thms,
- induction = induct',
- simps = simps}, thy11)
- end;
-
-fun gen_rep_datatype prep_term (config : datatype_config) after_qed alt_names raw_ts thy =
- let
- fun constr_of_term (Const (c, T)) = (c, T)
- | constr_of_term t =
- error ("Not a constant: " ^ Syntax.string_of_term_global thy t);
- fun no_constr (c, T) = error ("Bad constructor: "
- ^ Sign.extern_const thy c ^ "::"
- ^ Syntax.string_of_typ_global thy T);
- fun type_of_constr (cT as (_, T)) =
- let
- val frees = OldTerm.typ_tfrees T;
- val (tyco, vs) = ((apsnd o map) (dest_TFree) o dest_Type o snd o strip_type) T
- handle TYPE _ => no_constr cT
- val _ = if has_duplicates (eq_fst (op =)) vs then no_constr cT else ();
- val _ = if length frees <> length vs then no_constr cT else ();
- in (tyco, (vs, cT)) end;
-
- val raw_cs = AList.group (op =) (map (type_of_constr o constr_of_term o prep_term thy) raw_ts);
- val _ = case map_filter (fn (tyco, _) =>
- if Symtab.defined (get_datatypes thy) tyco then SOME tyco else NONE) raw_cs
- of [] => ()
- | tycos => error ("Type(s) " ^ commas (map quote tycos)
- ^ " already represented inductivly");
- val raw_vss = maps (map (map snd o fst) o snd) raw_cs;
- val ms = case distinct (op =) (map length raw_vss)
- of [n] => 0 upto n - 1
- | _ => error ("Different types in given constructors");
- fun inter_sort m = map (fn xs => nth xs m) raw_vss
- |> Library.foldr1 (Sorts.inter_sort (Sign.classes_of thy))
- val sorts = map inter_sort ms;
- val vs = Name.names Name.context Name.aT sorts;
-
- fun norm_constr (raw_vs, (c, T)) = (c, map_atyps
- (TFree o (the o AList.lookup (op =) (map fst raw_vs ~~ vs)) o fst o dest_TFree) T);
-
- val cs = map (apsnd (map norm_constr)) raw_cs;
- val dtyps_of_typ = map (dtyp_of_typ (map (rpair (map fst vs) o fst) cs))
- o fst o strip_type;
- val new_type_names = map Long_Name.base_name (the_default (map fst cs) alt_names);
-
- fun mk_spec (i, (tyco, constr)) = (i, (tyco,
- map (DtTFree o fst) vs,
- (map o apsnd) dtyps_of_typ constr))
- val descr = map_index mk_spec cs;
- val injs = DatatypeProp.make_injs [descr] vs;
- val half_distincts = map snd (DatatypeProp.make_distincts [descr] vs);
- val ind = DatatypeProp.make_ind [descr] vs;
- val rules = (map o map o map) Logic.close_form [[[ind]], injs, half_distincts];
-
- fun after_qed' raw_thms =
- let
- val [[[induct]], injs, half_distincts] =
- unflat rules (map Drule.zero_var_indexes_list raw_thms);
- (*FIXME somehow dubious*)
- in
- ProofContext.theory_result
- (prove_rep_datatype config alt_names new_type_names descr vs induct injs half_distincts)
- #-> after_qed
- end;
- in
- thy
- |> ProofContext.init
- |> Proof.theorem_i NONE after_qed' ((map o map) (rpair []) (flat rules))
- end;
-
-val rep_datatype = gen_rep_datatype Sign.cert_term;
-val rep_datatype_cmd = gen_rep_datatype Syntax.read_term_global default_datatype_config (K I);
-
-
-
-(******************************** add datatype ********************************)
-
-fun gen_add_datatype prep_typ (config : datatype_config) new_type_names dts thy =
- let
- val _ = Theory.requires thy "Datatype" "datatype definitions";
-
- (* this theory is used just for parsing *)
-
- val tmp_thy = thy |>
- Theory.copy |>
- Sign.add_types (map (fn (tvs, tname, mx, _) =>
- (tname, length tvs, mx)) dts);
-
- val (tyvars, _, _, _)::_ = dts;
- val (new_dts, types_syntax) = ListPair.unzip (map (fn (tvs, tname, mx, _) =>
- let val full_tname = Sign.full_name tmp_thy (Binding.map_name (Syntax.type_name mx) tname)
- in (case duplicates (op =) tvs of
- [] => if eq_set (tyvars, tvs) then ((full_tname, tvs), (tname, mx))
- else error ("Mutually recursive datatypes must have same type parameters")
- | dups => error ("Duplicate parameter(s) for datatype " ^ quote (Binding.str_of tname) ^
- " : " ^ commas dups))
- end) dts);
-
- val _ = (case duplicates (op =) (map fst new_dts) @ duplicates (op =) new_type_names of
- [] => () | dups => error ("Duplicate datatypes: " ^ commas dups));
-
- fun prep_dt_spec ((tvs, tname, mx, constrs), tname') (dts', constr_syntax, sorts, i) =
- let
- fun prep_constr (cname, cargs, mx') (constrs, constr_syntax', sorts') =
- let
- val (cargs', sorts'') = Library.foldl (prep_typ tmp_thy) (([], sorts'), cargs);
- val _ = (case fold (curry OldTerm.add_typ_tfree_names) cargs' [] \\ tvs of
- [] => ()
- | vs => error ("Extra type variables on rhs: " ^ commas vs))
- in (constrs @ [((if #flat_names config then Sign.full_name tmp_thy else
- Sign.full_name_path tmp_thy tname')
- (Binding.map_name (Syntax.const_name mx') cname),
- map (dtyp_of_typ new_dts) cargs')],
- constr_syntax' @ [(cname, mx')], sorts'')
- end handle ERROR msg => cat_error msg
- ("The error above occured in constructor " ^ quote (Binding.str_of cname) ^
- " of datatype " ^ quote (Binding.str_of tname));
-
- val (constrs', constr_syntax', sorts') =
- fold prep_constr constrs ([], [], sorts)
-
- in
- case duplicates (op =) (map fst constrs') of
- [] =>
- (dts' @ [(i, (Sign.full_name tmp_thy (Binding.map_name (Syntax.type_name mx) tname),
- map DtTFree tvs, constrs'))],
- constr_syntax @ [constr_syntax'], sorts', i + 1)
- | dups => error ("Duplicate constructors " ^ commas dups ^
- " in datatype " ^ quote (Binding.str_of tname))
- end;
-
- val (dts', constr_syntax, sorts', i) =
- fold prep_dt_spec (dts ~~ new_type_names) ([], [], [], 0);
- val sorts = sorts' @ (map (rpair (Sign.defaultS tmp_thy)) (tyvars \\ map fst sorts'));
- val dt_info = get_datatypes thy;
- val (descr, _) = unfold_datatypes tmp_thy dts' sorts dt_info dts' i;
- val _ = check_nonempty descr handle (exn as Datatype_Empty s) =>
- if #strict config then error ("Nonemptiness check failed for datatype " ^ s)
- else raise exn;
-
- val descr' = flat descr;
- val case_names_induct = mk_case_names_induct descr';
- val case_names_exhausts = mk_case_names_exhausts descr' (map #1 new_dts);
- in
- add_datatype_def
- (config : datatype_config) new_type_names descr sorts types_syntax constr_syntax dt_info
- case_names_induct case_names_exhausts thy
- end;
-
-val add_datatype = gen_add_datatype cert_typ;
-val add_datatype_cmd = gen_add_datatype read_typ default_datatype_config;
-
-
-
-(** package setup **)
-
-(* setup theory *)
-
-val setup =
- DatatypeRepProofs.distinctness_limit_setup #>
- simproc_setup #>
- trfun_setup #>
- DatatypeInterpretation.init;
-
-
-(* outer syntax *)
-
-local structure P = OuterParse and K = OuterKeyword in
-
-val datatype_decl =
- Scan.option (P.$$$ "(" |-- P.name --| P.$$$ ")") -- P.type_args -- P.binding -- P.opt_infix --
- (P.$$$ "=" |-- P.enum1 "|" (P.binding -- Scan.repeat P.typ -- P.opt_mixfix));
-
-fun mk_datatype args =
- let
- val names = map
- (fn ((((NONE, _), t), _), _) => Binding.name_of t | ((((SOME t, _), _), _), _) => t) args;
- val specs = map (fn ((((_, vs), t), mx), cons) =>
- (vs, t, mx, map (fn ((x, y), z) => (x, y, z)) cons)) args;
- in snd o add_datatype_cmd names specs end;
-
-val _ =
- OuterSyntax.command "datatype" "define inductive datatypes" K.thy_decl
- (P.and_list1 datatype_decl >> (Toplevel.theory o mk_datatype));
-
-val _ =
- OuterSyntax.command "rep_datatype" "represent existing types inductively" K.thy_goal
- (Scan.option (P.$$$ "(" |-- Scan.repeat1 P.name --| P.$$$ ")") -- Scan.repeat1 P.term
- >> (fn (alt_names, ts) => Toplevel.print
- o Toplevel.theory_to_proof (rep_datatype_cmd alt_names ts)));
-
-end;
-
-
-(* document antiquotation *)
-
-val _ = ThyOutput.antiquotation "datatype" Args.tyname
- (fn {source = src, context = ctxt, ...} => fn dtco =>
- let
- val thy = ProofContext.theory_of ctxt;
- val (vs, cos) = the_datatype_spec thy dtco;
- val ty = Type (dtco, map TFree vs);
- fun pretty_typ_bracket (ty as Type (_, _ :: _)) =
- Pretty.enclose "(" ")" [Syntax.pretty_typ ctxt ty]
- | pretty_typ_bracket ty =
- Syntax.pretty_typ ctxt ty;
- fun pretty_constr (co, tys) =
- (Pretty.block o Pretty.breaks)
- (Syntax.pretty_term ctxt (Const (co, tys ---> ty)) ::
- map pretty_typ_bracket tys);
- val pretty_datatype =
- Pretty.block
- (Pretty.command "datatype" :: Pretty.brk 1 ::
- Syntax.pretty_typ ctxt ty ::
- Pretty.str " =" :: Pretty.brk 1 ::
- flat (separate [Pretty.brk 1, Pretty.str "| "]
- (map (single o pretty_constr) cos)));
- in ThyOutput.output (ThyOutput.maybe_pretty_source (K pretty_datatype) src [()]) end);
-
-end;
-
--- a/src/HOL/Tools/datatype_package/datatype_realizer.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/datatype_package/datatype_realizer.ML Fri Jun 19 21:08:07 2009 +0200
@@ -217,7 +217,7 @@
if ! Proofterm.proofs < 2 then thy
else let
val _ = message config "Adding realizers for induction and case analysis ..."
- val infos = map (DatatypePackage.the_datatype thy) names;
+ val infos = map (Datatype.the_datatype thy) names;
val info :: _ = infos;
in
thy
@@ -225,6 +225,6 @@
|> fold_rev (make_casedists (#sorts info)) infos
end;
-val setup = DatatypePackage.interpretation add_dt_realizers;
+val setup = Datatype.interpretation add_dt_realizers;
end;
--- a/src/HOL/Tools/datatype_package/datatype_rep_proofs.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/datatype_package/datatype_rep_proofs.ML Fri Jun 19 21:08:07 2009 +0200
@@ -183,7 +183,7 @@
((1 upto (length constrs)) ~~ constrs)) (descr' ~~ rep_set_names');
val ({raw_induct = rep_induct, intrs = rep_intrs, ...}, thy2) =
- InductivePackage.add_inductive_global (serial_string ())
+ Inductive.add_inductive_global (serial_string ())
{quiet_mode = #quiet config, verbose = false, kind = Thm.internalK,
alt_name = Binding.name big_rec_name, coind = false, no_elim = true, no_ind = false,
skip_mono = true, fork_mono = false}
@@ -195,7 +195,7 @@
val (typedefs, thy3) = thy2 |>
parent_path (#flat_names config) |>
fold_map (fn ((((name, mx), tvs), c), name') =>
- TypedefPackage.add_typedef false (SOME (Binding.name name')) (name, tvs, mx)
+ Typedef.add_typedef false (SOME (Binding.name name')) (name, tvs, mx)
(Collect $ Const (c, UnivT')) NONE
(rtac exI 1 THEN rtac CollectI 1 THEN
QUIET_BREADTH_FIRST (has_fewer_prems 1)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/function_package/fundef.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,226 @@
+(* Title: HOL/Tools/function_package/fundef.ML
+ Author: Alexander Krauss, TU Muenchen
+
+A package for general recursive function definitions.
+Isar commands.
+*)
+
+signature FUNDEF =
+sig
+ val add_fundef : (binding * typ option * mixfix) list
+ -> (Attrib.binding * term) list
+ -> FundefCommon.fundef_config
+ -> local_theory
+ -> Proof.state
+ val add_fundef_cmd : (binding * string option * mixfix) list
+ -> (Attrib.binding * string) list
+ -> FundefCommon.fundef_config
+ -> local_theory
+ -> Proof.state
+
+ val termination_proof : term option -> local_theory -> Proof.state
+ val termination_proof_cmd : string option -> local_theory -> Proof.state
+ val termination : term option -> local_theory -> Proof.state
+ val termination_cmd : string option -> local_theory -> Proof.state
+
+ val setup : theory -> theory
+ val get_congs : Proof.context -> thm list
+end
+
+
+structure Fundef : FUNDEF =
+struct
+
+open FundefLib
+open FundefCommon
+
+val simp_attribs = map (Attrib.internal o K)
+ [Simplifier.simp_add,
+ Code.add_default_eqn_attribute,
+ Nitpick_Const_Simp_Thms.add,
+ Quickcheck_RecFun_Simp_Thms.add]
+
+val psimp_attribs = map (Attrib.internal o K)
+ [Simplifier.simp_add,
+ Nitpick_Const_Psimp_Thms.add]
+
+fun note_theorem ((name, atts), ths) =
+ LocalTheory.note Thm.generatedK ((Binding.qualified_name name, atts), ths)
+
+fun mk_defname fixes = fixes |> map (fst o fst) |> space_implode "_"
+
+fun add_simps fnames post sort extra_qualify label moreatts simps lthy =
+ let
+ val spec = post simps
+ |> map (apfst (apsnd (fn ats => moreatts @ ats)))
+ |> map (apfst (apfst extra_qualify))
+
+ val (saved_spec_simps, lthy) =
+ fold_map (LocalTheory.note Thm.generatedK) spec lthy
+
+ val saved_simps = flat (map snd saved_spec_simps)
+ val simps_by_f = sort saved_simps
+
+ fun add_for_f fname simps =
+ note_theorem ((Long_Name.qualify fname label, []), simps) #> snd
+ in
+ (saved_simps,
+ fold2 add_for_f fnames simps_by_f lthy)
+ end
+
+fun gen_add_fundef is_external prep default_constraint fixspec eqns config lthy =
+ let
+ val constrn_fxs = map (fn (b, T, mx) => (b, SOME (the_default default_constraint T), mx))
+ val ((fixes0, spec0), ctxt') = prep (constrn_fxs fixspec) eqns lthy
+ val fixes = map (apfst (apfst Binding.name_of)) fixes0;
+ val spec = map (fn (bnd, prop) => (bnd, [prop])) spec0;
+ val (eqs, post, sort_cont, cnames) = FundefCommon.get_preproc lthy config ctxt' fixes spec
+
+ val defname = mk_defname fixes
+
+ val ((goalstate, cont), lthy) =
+ FundefMutual.prepare_fundef_mutual config defname fixes eqs lthy
+
+ fun afterqed [[proof]] lthy =
+ let
+ val FundefResult {fs, R, psimps, trsimps, simple_pinducts, termination,
+ domintros, cases, ...} =
+ cont (Thm.close_derivation proof)
+
+ val fnames = map (fst o fst) fixes
+ val qualify = Long_Name.qualify defname
+ val addsmps = add_simps fnames post sort_cont
+
+ val (((psimps', pinducts'), (_, [termination'])), lthy) =
+ lthy
+ |> addsmps (Binding.qualify false "partial") "psimps"
+ psimp_attribs psimps
+ ||> fold_option (snd oo addsmps I "simps" simp_attribs) trsimps
+ ||>> note_theorem ((qualify "pinduct",
+ [Attrib.internal (K (RuleCases.case_names cnames)),
+ Attrib.internal (K (RuleCases.consumes 1)),
+ Attrib.internal (K (Induct.induct_pred ""))]), simple_pinducts)
+ ||>> note_theorem ((qualify "termination", []), [termination])
+ ||> (snd o note_theorem ((qualify "cases",
+ [Attrib.internal (K (RuleCases.case_names cnames))]), [cases]))
+ ||> fold_option (snd oo curry note_theorem (qualify "domintros", [])) domintros
+
+ val cdata = FundefCtxData { add_simps=addsmps, case_names=cnames, psimps=psimps',
+ pinducts=snd pinducts', termination=termination',
+ fs=fs, R=R, defname=defname }
+ val _ =
+ if not is_external then ()
+ else Specification.print_consts lthy (K false) (map fst fixes)
+ in
+ lthy
+ |> LocalTheory.declaration (add_fundef_data o morph_fundef_data cdata)
+ end
+ in
+ lthy
+ |> is_external ? LocalTheory.set_group (serial_string ())
+ |> Proof.theorem_i NONE afterqed [[(Logic.unprotect (concl_of goalstate), [])]]
+ |> Proof.refine (Method.primitive_text (fn _ => goalstate)) |> Seq.hd
+ end
+
+val add_fundef = gen_add_fundef false Specification.check_spec (TypeInfer.anyT HOLogic.typeS)
+val add_fundef_cmd = gen_add_fundef true Specification.read_spec "_::type"
+
+fun gen_termination_proof prep_term raw_term_opt lthy =
+ let
+ val term_opt = Option.map (prep_term lthy) raw_term_opt
+ val data = the (case term_opt of
+ SOME t => (import_fundef_data t lthy
+ handle Option.Option =>
+ error ("Not a function: " ^ quote (Syntax.string_of_term lthy t)))
+ | NONE => (import_last_fundef lthy handle Option.Option => error "Not a function"))
+
+ val FundefCtxData { termination, R, add_simps, case_names, psimps,
+ pinducts, defname, ...} = data
+ val domT = domain_type (fastype_of R)
+ val goal = HOLogic.mk_Trueprop
+ (HOLogic.mk_all ("x", domT, mk_acc domT R $ Free ("x", domT)))
+ fun afterqed [[totality]] lthy =
+ let
+ val totality = Thm.close_derivation totality
+ val remove_domain_condition =
+ full_simplify (HOL_basic_ss addsimps [totality, True_implies_equals])
+ val tsimps = map remove_domain_condition psimps
+ val tinduct = map remove_domain_condition pinducts
+ val qualify = Long_Name.qualify defname;
+ in
+ lthy
+ |> add_simps I "simps" simp_attribs tsimps |> snd
+ |> note_theorem
+ ((qualify "induct",
+ [Attrib.internal (K (RuleCases.case_names case_names))]),
+ tinduct) |> snd
+ end
+ in
+ lthy
+ |> ProofContext.note_thmss ""
+ [((Binding.empty, [ContextRules.rule_del]), [([allI], [])])] |> snd
+ |> ProofContext.note_thmss ""
+ [((Binding.empty, [ContextRules.intro_bang (SOME 1)]), [([allI], [])])] |> snd
+ |> ProofContext.note_thmss ""
+ [((Binding.name "termination", [ContextRules.intro_bang (SOME 0)]),
+ [([Goal.norm_result termination], [])])] |> snd
+ |> Proof.theorem_i NONE afterqed [[(goal, [])]]
+ end
+
+val termination_proof = gen_termination_proof Syntax.check_term;
+val termination_proof_cmd = gen_termination_proof Syntax.read_term;
+
+fun termination term_opt lthy =
+ lthy
+ |> LocalTheory.set_group (serial_string ())
+ |> termination_proof term_opt;
+
+fun termination_cmd term_opt lthy =
+ lthy
+ |> LocalTheory.set_group (serial_string ())
+ |> termination_proof_cmd term_opt;
+
+
+(* Datatype hook to declare datatype congs as "fundef_congs" *)
+
+
+fun add_case_cong n thy =
+ Context.theory_map (FundefCtxTree.map_fundef_congs (Thm.add_thm
+ (Datatype.get_datatype thy n |> the
+ |> #case_cong
+ |> safe_mk_meta_eq)))
+ thy
+
+val setup_case_cong = Datatype.interpretation (K (fold add_case_cong))
+
+
+(* setup *)
+
+val setup =
+ Attrib.setup @{binding fundef_cong}
+ (Attrib.add_del FundefCtxTree.cong_add FundefCtxTree.cong_del)
+ "declaration of congruence rule for function definitions"
+ #> setup_case_cong
+ #> FundefRelation.setup
+ #> FundefCommon.TerminationSimps.setup
+
+val get_congs = FundefCtxTree.get_fundef_congs
+
+
+(* outer syntax *)
+
+local structure P = OuterParse and K = OuterKeyword in
+
+val _ =
+ OuterSyntax.local_theory_to_proof "function" "define general recursive functions" K.thy_goal
+ (fundef_parser default_config
+ >> (fn ((config, fixes), statements) => add_fundef_cmd fixes statements config));
+
+val _ =
+ OuterSyntax.local_theory_to_proof "termination" "prove termination of a recursive function" K.thy_goal
+ (Scan.option P.term >> termination_cmd);
+
+end;
+
+
+end
--- a/src/HOL/Tools/function_package/fundef_datatype.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/function_package/fundef_datatype.ML Fri Jun 19 21:08:07 2009 +0200
@@ -40,7 +40,7 @@
let
val (hd, args) = strip_comb t
in
- (((case DatatypePackage.datatype_of_constr thy (fst (dest_Const hd)) of
+ (((case Datatype.datatype_of_constr thy (fst (dest_Const hd)) of
SOME _ => ()
| NONE => err "Non-constructor pattern")
handle TERM ("dest_Const", _) => err "Non-constructor patterns");
@@ -103,7 +103,7 @@
fun inst_constrs_of thy (T as Type (name, _)) =
map (fn (Cn,CT) => Envir.subst_TVars (Sign.typ_match thy (body_type CT, T) Vartab.empty) (Const (Cn, CT)))
- (the (DatatypePackage.get_datatype_constrs thy name))
+ (the (Datatype.get_datatype_constrs thy name))
| inst_constrs_of thy _ = raise Match
@@ -144,7 +144,7 @@
let
val T = fastype_of v
val (tname, _) = dest_Type T
- val {exhaustion=case_thm, ...} = DatatypePackage.the_datatype thy tname
+ val {exhaustion=case_thm, ...} = Datatype.the_datatype thy tname
val constrs = inst_constrs_of thy T
val c_cases = map (constr_case thy P idx (v :: vs) pts) constrs
in
@@ -211,7 +211,7 @@
SOME (Method.Source_i (Args.src (("HOL.auto", []), Position.none))))
fun termination_by method int =
- FundefPackage.termination_proof NONE
+ Fundef.termination_proof NONE
#> Proof.global_future_terminal_proof
(Method.Basic (method, Position.none), NONE) int
@@ -313,8 +313,8 @@
|> termination_by (FundefCommon.get_termination_prover lthy) int
end;
-val add_fun = gen_fun FundefPackage.add_fundef
-val add_fun_cmd = gen_fun FundefPackage.add_fundef_cmd
+val add_fun = gen_fun Fundef.add_fundef
+val add_fun_cmd = gen_fun Fundef.add_fundef_cmd
--- a/src/HOL/Tools/function_package/fundef_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-(* Title: HOL/Tools/function_package/fundef_package.ML
- Author: Alexander Krauss, TU Muenchen
-
-A package for general recursive function definitions.
-Isar commands.
-*)
-
-signature FUNDEF_PACKAGE =
-sig
- val add_fundef : (binding * typ option * mixfix) list
- -> (Attrib.binding * term) list
- -> FundefCommon.fundef_config
- -> local_theory
- -> Proof.state
- val add_fundef_cmd : (binding * string option * mixfix) list
- -> (Attrib.binding * string) list
- -> FundefCommon.fundef_config
- -> local_theory
- -> Proof.state
-
- val termination_proof : term option -> local_theory -> Proof.state
- val termination_proof_cmd : string option -> local_theory -> Proof.state
- val termination : term option -> local_theory -> Proof.state
- val termination_cmd : string option -> local_theory -> Proof.state
-
- val setup : theory -> theory
- val get_congs : Proof.context -> thm list
-end
-
-
-structure FundefPackage : FUNDEF_PACKAGE =
-struct
-
-open FundefLib
-open FundefCommon
-
-val simp_attribs = map (Attrib.internal o K)
- [Simplifier.simp_add,
- Code.add_default_eqn_attribute,
- Nitpick_Const_Simp_Thms.add,
- Quickcheck_RecFun_Simp_Thms.add]
-
-val psimp_attribs = map (Attrib.internal o K)
- [Simplifier.simp_add,
- Nitpick_Const_Psimp_Thms.add]
-
-fun note_theorem ((name, atts), ths) =
- LocalTheory.note Thm.generatedK ((Binding.qualified_name name, atts), ths)
-
-fun mk_defname fixes = fixes |> map (fst o fst) |> space_implode "_"
-
-fun add_simps fnames post sort extra_qualify label moreatts simps lthy =
- let
- val spec = post simps
- |> map (apfst (apsnd (fn ats => moreatts @ ats)))
- |> map (apfst (apfst extra_qualify))
-
- val (saved_spec_simps, lthy) =
- fold_map (LocalTheory.note Thm.generatedK) spec lthy
-
- val saved_simps = flat (map snd saved_spec_simps)
- val simps_by_f = sort saved_simps
-
- fun add_for_f fname simps =
- note_theorem ((Long_Name.qualify fname label, []), simps) #> snd
- in
- (saved_simps,
- fold2 add_for_f fnames simps_by_f lthy)
- end
-
-fun gen_add_fundef is_external prep default_constraint fixspec eqns config lthy =
- let
- val constrn_fxs = map (fn (b, T, mx) => (b, SOME (the_default default_constraint T), mx))
- val ((fixes0, spec0), ctxt') = prep (constrn_fxs fixspec) eqns lthy
- val fixes = map (apfst (apfst Binding.name_of)) fixes0;
- val spec = map (fn (bnd, prop) => (bnd, [prop])) spec0;
- val (eqs, post, sort_cont, cnames) = FundefCommon.get_preproc lthy config ctxt' fixes spec
-
- val defname = mk_defname fixes
-
- val ((goalstate, cont), lthy) =
- FundefMutual.prepare_fundef_mutual config defname fixes eqs lthy
-
- fun afterqed [[proof]] lthy =
- let
- val FundefResult {fs, R, psimps, trsimps, simple_pinducts, termination,
- domintros, cases, ...} =
- cont (Thm.close_derivation proof)
-
- val fnames = map (fst o fst) fixes
- val qualify = Long_Name.qualify defname
- val addsmps = add_simps fnames post sort_cont
-
- val (((psimps', pinducts'), (_, [termination'])), lthy) =
- lthy
- |> addsmps (Binding.qualify false "partial") "psimps"
- psimp_attribs psimps
- ||> fold_option (snd oo addsmps I "simps" simp_attribs) trsimps
- ||>> note_theorem ((qualify "pinduct",
- [Attrib.internal (K (RuleCases.case_names cnames)),
- Attrib.internal (K (RuleCases.consumes 1)),
- Attrib.internal (K (Induct.induct_pred ""))]), simple_pinducts)
- ||>> note_theorem ((qualify "termination", []), [termination])
- ||> (snd o note_theorem ((qualify "cases",
- [Attrib.internal (K (RuleCases.case_names cnames))]), [cases]))
- ||> fold_option (snd oo curry note_theorem (qualify "domintros", [])) domintros
-
- val cdata = FundefCtxData { add_simps=addsmps, case_names=cnames, psimps=psimps',
- pinducts=snd pinducts', termination=termination',
- fs=fs, R=R, defname=defname }
- val _ =
- if not is_external then ()
- else Specification.print_consts lthy (K false) (map fst fixes)
- in
- lthy
- |> LocalTheory.declaration (add_fundef_data o morph_fundef_data cdata)
- end
- in
- lthy
- |> is_external ? LocalTheory.set_group (serial_string ())
- |> Proof.theorem_i NONE afterqed [[(Logic.unprotect (concl_of goalstate), [])]]
- |> Proof.refine (Method.primitive_text (fn _ => goalstate)) |> Seq.hd
- end
-
-val add_fundef = gen_add_fundef false Specification.check_spec (TypeInfer.anyT HOLogic.typeS)
-val add_fundef_cmd = gen_add_fundef true Specification.read_spec "_::type"
-
-fun gen_termination_proof prep_term raw_term_opt lthy =
- let
- val term_opt = Option.map (prep_term lthy) raw_term_opt
- val data = the (case term_opt of
- SOME t => (import_fundef_data t lthy
- handle Option.Option =>
- error ("Not a function: " ^ quote (Syntax.string_of_term lthy t)))
- | NONE => (import_last_fundef lthy handle Option.Option => error "Not a function"))
-
- val FundefCtxData { termination, R, add_simps, case_names, psimps,
- pinducts, defname, ...} = data
- val domT = domain_type (fastype_of R)
- val goal = HOLogic.mk_Trueprop
- (HOLogic.mk_all ("x", domT, mk_acc domT R $ Free ("x", domT)))
- fun afterqed [[totality]] lthy =
- let
- val totality = Thm.close_derivation totality
- val remove_domain_condition =
- full_simplify (HOL_basic_ss addsimps [totality, True_implies_equals])
- val tsimps = map remove_domain_condition psimps
- val tinduct = map remove_domain_condition pinducts
- val qualify = Long_Name.qualify defname;
- in
- lthy
- |> add_simps I "simps" simp_attribs tsimps |> snd
- |> note_theorem
- ((qualify "induct",
- [Attrib.internal (K (RuleCases.case_names case_names))]),
- tinduct) |> snd
- end
- in
- lthy
- |> ProofContext.note_thmss ""
- [((Binding.empty, [ContextRules.rule_del]), [([allI], [])])] |> snd
- |> ProofContext.note_thmss ""
- [((Binding.empty, [ContextRules.intro_bang (SOME 1)]), [([allI], [])])] |> snd
- |> ProofContext.note_thmss ""
- [((Binding.name "termination", [ContextRules.intro_bang (SOME 0)]),
- [([Goal.norm_result termination], [])])] |> snd
- |> Proof.theorem_i NONE afterqed [[(goal, [])]]
- end
-
-val termination_proof = gen_termination_proof Syntax.check_term;
-val termination_proof_cmd = gen_termination_proof Syntax.read_term;
-
-fun termination term_opt lthy =
- lthy
- |> LocalTheory.set_group (serial_string ())
- |> termination_proof term_opt;
-
-fun termination_cmd term_opt lthy =
- lthy
- |> LocalTheory.set_group (serial_string ())
- |> termination_proof_cmd term_opt;
-
-
-(* Datatype hook to declare datatype congs as "fundef_congs" *)
-
-
-fun add_case_cong n thy =
- Context.theory_map (FundefCtxTree.map_fundef_congs (Thm.add_thm
- (DatatypePackage.get_datatype thy n |> the
- |> #case_cong
- |> safe_mk_meta_eq)))
- thy
-
-val setup_case_cong = DatatypePackage.interpretation (K (fold add_case_cong))
-
-
-(* setup *)
-
-val setup =
- Attrib.setup @{binding fundef_cong}
- (Attrib.add_del FundefCtxTree.cong_add FundefCtxTree.cong_del)
- "declaration of congruence rule for function definitions"
- #> setup_case_cong
- #> FundefRelation.setup
- #> FundefCommon.TerminationSimps.setup
-
-val get_congs = FundefCtxTree.get_fundef_congs
-
-
-(* outer syntax *)
-
-local structure P = OuterParse and K = OuterKeyword in
-
-val _ =
- OuterSyntax.local_theory_to_proof "function" "define general recursive functions" K.thy_goal
- (fundef_parser default_config
- >> (fn ((config, fixes), statements) => add_fundef_cmd fixes statements config));
-
-val _ =
- OuterSyntax.local_theory_to_proof "termination" "prove termination of a recursive function" K.thy_goal
- (Scan.option P.term >> termination_cmd);
-
-end;
-
-
-end
--- a/src/HOL/Tools/function_package/inductive_wrap.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/function_package/inductive_wrap.ML Fri Jun 19 21:08:07 2009 +0200
@@ -1,5 +1,4 @@
(* Title: HOL/Tools/function_package/inductive_wrap.ML
- ID: $Id$
Author: Alexander Krauss, TU Muenchen
@@ -40,7 +39,7 @@
fun inductive_def defs (((R, T), mixfix), lthy) =
let
val ({intrs = intrs_gen, elims = [elim_gen], preds = [ Rdef ], induct, ...}, lthy) =
- InductivePackage.add_inductive_i
+ Inductive.add_inductive_i
{quiet_mode = false,
verbose = ! Toplevel.debug,
kind = Thm.internalK,
--- a/src/HOL/Tools/function_package/pattern_split.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/function_package/pattern_split.ML Fri Jun 19 21:08:07 2009 +0200
@@ -41,7 +41,7 @@
(* This is copied from "fundef_datatype.ML" *)
fun inst_constrs_of thy (T as Type (name, _)) =
map (fn (Cn,CT) => Envir.subst_TVars (Sign.typ_match thy (body_type CT, T) Vartab.empty) (Const (Cn, CT)))
- (the (DatatypePackage.get_datatype_constrs thy name))
+ (the (Datatype.get_datatype_constrs thy name))
| inst_constrs_of thy T = raise TYPE ("inst_constrs_of", [T], [])
--- a/src/HOL/Tools/function_package/size.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/function_package/size.ML Fri Jun 19 21:08:07 2009 +0200
@@ -44,14 +44,14 @@
| SOME t => t);
fun is_poly thy (DtType (name, dts)) =
- (case DatatypePackage.get_datatype thy name of
+ (case Datatype.get_datatype thy name of
NONE => false
| SOME _ => exists (is_poly thy) dts)
| is_poly _ _ = true;
fun constrs_of thy name =
let
- val {descr, index, ...} = DatatypePackage.the_datatype thy name
+ val {descr, index, ...} = Datatype.the_datatype thy name
val SOME (_, _, constrs) = AList.lookup op = descr index
in constrs end;
@@ -220,7 +220,7 @@
fun add_size_thms config (new_type_names as name :: _) thy =
let
- val info as {descr, alt_names, ...} = DatatypePackage.the_datatype thy name;
+ val info as {descr, alt_names, ...} = Datatype.the_datatype thy name;
val prefix = Long_Name.map_base_name (K (space_implode "_"
(the_default (map Long_Name.base_name new_type_names) alt_names))) name;
val no_size = exists (fn (_, (_, _, constrs)) => exists (fn (_, cargs) => exists (fn dt =>
@@ -237,6 +237,6 @@
val size_thms = snd oo (the oo lookup_size);
-val setup = DatatypePackage.interpretation add_size_thms;
+val setup = Datatype.interpretation add_size_thms;
end;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/inductive.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,968 @@
+(* Title: HOL/Tools/inductive.ML
+ Author: Lawrence C Paulson, Cambridge University Computer Laboratory
+ Author: Stefan Berghofer and Markus Wenzel, TU Muenchen
+
+(Co)Inductive Definition module for HOL.
+
+Features:
+ * least or greatest fixedpoints
+ * mutually recursive definitions
+ * definitions involving arbitrary monotone operators
+ * automatically proves introduction and elimination rules
+
+ Introduction rules have the form
+ [| M Pj ti, ..., Q x, ... |] ==> Pk t
+ where M is some monotone operator (usually the identity)
+ Q x is any side condition on the free variables
+ ti, t are any terms
+ Pj, Pk are two of the predicates being defined in mutual recursion
+*)
+
+signature BASIC_INDUCTIVE =
+sig
+ type inductive_result
+ val morph_result: morphism -> inductive_result -> inductive_result
+ type inductive_info
+ val the_inductive: Proof.context -> string -> inductive_info
+ val print_inductives: Proof.context -> unit
+ val mono_add: attribute
+ val mono_del: attribute
+ val get_monos: Proof.context -> thm list
+ val mk_cases: Proof.context -> term -> thm
+ val inductive_forall_name: string
+ val inductive_forall_def: thm
+ val rulify: thm -> thm
+ val inductive_cases: (Attrib.binding * string list) list -> local_theory ->
+ thm list list * local_theory
+ val inductive_cases_i: (Attrib.binding * term list) list -> local_theory ->
+ thm list list * local_theory
+ type inductive_flags
+ val add_inductive_i:
+ inductive_flags -> ((binding * typ) * mixfix) list ->
+ (string * typ) list -> (Attrib.binding * term) list -> thm list -> local_theory ->
+ inductive_result * local_theory
+ val add_inductive: bool -> bool ->
+ (binding * string option * mixfix) list ->
+ (binding * string option * mixfix) list ->
+ (Attrib.binding * string) list ->
+ (Facts.ref * Attrib.src list) list ->
+ bool -> local_theory -> inductive_result * local_theory
+ val add_inductive_global: string -> inductive_flags ->
+ ((binding * typ) * mixfix) list -> (string * typ) list -> (Attrib.binding * term) list ->
+ thm list -> theory -> inductive_result * theory
+ val arities_of: thm -> (string * int) list
+ val params_of: thm -> term list
+ val partition_rules: thm -> thm list -> (string * thm list) list
+ val partition_rules': thm -> (thm * 'a) list -> (string * (thm * 'a) list) list
+ val unpartition_rules: thm list -> (string * 'a list) list -> 'a list
+ val infer_intro_vars: thm -> int -> thm list -> term list list
+ val setup: theory -> theory
+end;
+
+signature INDUCTIVE =
+sig
+ include BASIC_INDUCTIVE
+ type add_ind_def
+ val declare_rules: string -> binding -> bool -> bool -> string list ->
+ thm list -> binding list -> Attrib.src list list -> (thm * string list) list ->
+ thm -> local_theory -> thm list * thm list * thm * local_theory
+ val add_ind_def: add_ind_def
+ val gen_add_inductive_i: add_ind_def -> inductive_flags ->
+ ((binding * typ) * mixfix) list -> (string * typ) list -> (Attrib.binding * term) list ->
+ thm list -> local_theory -> inductive_result * local_theory
+ val gen_add_inductive: add_ind_def -> bool -> bool ->
+ (binding * string option * mixfix) list ->
+ (binding * string option * mixfix) list ->
+ (Attrib.binding * string) list -> (Facts.ref * Attrib.src list) list ->
+ bool -> local_theory -> inductive_result * local_theory
+ val gen_ind_decl: add_ind_def -> bool ->
+ OuterParse.token list -> (bool -> local_theory -> local_theory) * OuterParse.token list
+end;
+
+structure Inductive: INDUCTIVE =
+struct
+
+
+(** theory context references **)
+
+val inductive_forall_name = "HOL.induct_forall";
+val inductive_forall_def = thm "induct_forall_def";
+val inductive_conj_name = "HOL.induct_conj";
+val inductive_conj_def = thm "induct_conj_def";
+val inductive_conj = thms "induct_conj";
+val inductive_atomize = thms "induct_atomize";
+val inductive_rulify = thms "induct_rulify";
+val inductive_rulify_fallback = thms "induct_rulify_fallback";
+
+val notTrueE = TrueI RSN (2, notE);
+val notFalseI = Seq.hd (atac 1 notI);
+val simp_thms' = map (fn s => mk_meta_eq (the (find_first
+ (equal (OldGoals.read_prop @{theory HOL} s) o prop_of) simp_thms)))
+ ["(~True) = False", "(~False) = True",
+ "(True --> ?P) = ?P", "(False --> ?P) = True",
+ "(?P & True) = ?P", "(True & ?P) = ?P"];
+
+
+
+(** context data **)
+
+type inductive_result =
+ {preds: term list, elims: thm list, raw_induct: thm,
+ induct: thm, intrs: thm list};
+
+fun morph_result phi {preds, elims, raw_induct: thm, induct, intrs} =
+ let
+ val term = Morphism.term phi;
+ val thm = Morphism.thm phi;
+ val fact = Morphism.fact phi;
+ in
+ {preds = map term preds, elims = fact elims, raw_induct = thm raw_induct,
+ induct = thm induct, intrs = fact intrs}
+ end;
+
+type inductive_info =
+ {names: string list, coind: bool} * inductive_result;
+
+structure InductiveData = GenericDataFun
+(
+ type T = inductive_info Symtab.table * thm list;
+ val empty = (Symtab.empty, []);
+ val extend = I;
+ fun merge _ ((tab1, monos1), (tab2, monos2)) =
+ (Symtab.merge (K true) (tab1, tab2), Thm.merge_thms (monos1, monos2));
+);
+
+val get_inductives = InductiveData.get o Context.Proof;
+
+fun print_inductives ctxt =
+ let
+ val (tab, monos) = get_inductives ctxt;
+ val space = Consts.space_of (ProofContext.consts_of ctxt);
+ in
+ [Pretty.strs ("(co)inductives:" :: map #1 (NameSpace.extern_table (space, tab))),
+ Pretty.big_list "monotonicity rules:" (map (ProofContext.pretty_thm ctxt) monos)]
+ |> Pretty.chunks |> Pretty.writeln
+ end;
+
+
+(* get and put data *)
+
+fun the_inductive ctxt name =
+ (case Symtab.lookup (#1 (get_inductives ctxt)) name of
+ NONE => error ("Unknown (co)inductive predicate " ^ quote name)
+ | SOME info => info);
+
+fun put_inductives names info = InductiveData.map
+ (apfst (fold (fn name => Symtab.update (name, info)) names));
+
+
+
+(** monotonicity rules **)
+
+val get_monos = #2 o get_inductives;
+val map_monos = InductiveData.map o apsnd;
+
+fun mk_mono thm =
+ let
+ val concl = concl_of thm;
+ fun eq2mono thm' = [thm' RS (thm' RS eq_to_mono)] @
+ (case concl of
+ (_ $ (_ $ (Const ("Not", _) $ _) $ _)) => []
+ | _ => [thm' RS (thm' RS eq_to_mono2)]);
+ fun dest_less_concl thm = dest_less_concl (thm RS le_funD)
+ handle THM _ => thm RS le_boolD
+ in
+ case concl of
+ Const ("==", _) $ _ $ _ => eq2mono (thm RS meta_eq_to_obj_eq)
+ | _ $ (Const ("op =", _) $ _ $ _) => eq2mono thm
+ | _ $ (Const ("HOL.ord_class.less_eq", _) $ _ $ _) =>
+ [dest_less_concl (Seq.hd (REPEAT (FIRSTGOAL
+ (resolve_tac [le_funI, le_boolI'])) thm))]
+ | _ => [thm]
+ end handle THM _ => error ("Bad monotonicity theorem:\n" ^ Display.string_of_thm thm);
+
+val mono_add = Thm.declaration_attribute (map_monos o fold Thm.add_thm o mk_mono);
+val mono_del = Thm.declaration_attribute (map_monos o fold Thm.del_thm o mk_mono);
+
+
+
+(** misc utilities **)
+
+fun message quiet_mode s = if quiet_mode then () else writeln s;
+fun clean_message quiet_mode s = if ! quick_and_dirty then () else message quiet_mode s;
+
+fun coind_prefix true = "co"
+ | coind_prefix false = "";
+
+fun log (b:int) m n = if m >= n then 0 else 1 + log b (b * m) n;
+
+fun make_bool_args f g [] i = []
+ | make_bool_args f g (x :: xs) i =
+ (if i mod 2 = 0 then f x else g x) :: make_bool_args f g xs (i div 2);
+
+fun make_bool_args' xs =
+ make_bool_args (K HOLogic.false_const) (K HOLogic.true_const) xs;
+
+fun find_arg T x [] = sys_error "find_arg"
+ | find_arg T x ((p as (_, (SOME _, _))) :: ps) =
+ apsnd (cons p) (find_arg T x ps)
+ | find_arg T x ((p as (U, (NONE, y))) :: ps) =
+ if (T: typ) = U then (y, (U, (SOME x, y)) :: ps)
+ else apsnd (cons p) (find_arg T x ps);
+
+fun make_args Ts xs =
+ map (fn (T, (NONE, ())) => Const (@{const_name undefined}, T) | (_, (SOME t, ())) => t)
+ (fold (fn (t, T) => snd o find_arg T t) xs (map (rpair (NONE, ())) Ts));
+
+fun make_args' Ts xs Us =
+ fst (fold_map (fn T => find_arg T ()) Us (Ts ~~ map (pair NONE) xs));
+
+fun dest_predicate cs params t =
+ let
+ val k = length params;
+ val (c, ts) = strip_comb t;
+ val (xs, ys) = chop k ts;
+ val i = find_index_eq c cs;
+ in
+ if xs = params andalso i >= 0 then
+ SOME (c, i, ys, chop (length ys)
+ (List.drop (binder_types (fastype_of c), k)))
+ else NONE
+ end;
+
+fun mk_names a 0 = []
+ | mk_names a 1 = [a]
+ | mk_names a n = map (fn i => a ^ string_of_int i) (1 upto n);
+
+
+
+(** process rules **)
+
+local
+
+fun err_in_rule ctxt name t msg =
+ error (cat_lines ["Ill-formed introduction rule " ^ quote name,
+ Syntax.string_of_term ctxt t, msg]);
+
+fun err_in_prem ctxt name t p msg =
+ error (cat_lines ["Ill-formed premise", Syntax.string_of_term ctxt p,
+ "in introduction rule " ^ quote name, Syntax.string_of_term ctxt t, msg]);
+
+val bad_concl = "Conclusion of introduction rule must be an inductive predicate";
+
+val bad_ind_occ = "Inductive predicate occurs in argument of inductive predicate";
+
+val bad_app = "Inductive predicate must be applied to parameter(s) ";
+
+fun atomize_term thy = MetaSimplifier.rewrite_term thy inductive_atomize [];
+
+in
+
+fun check_rule ctxt cs params ((binding, att), rule) =
+ let
+ val err_name = Binding.str_of binding;
+ val params' = Term.variant_frees rule (Logic.strip_params rule);
+ val frees = rev (map Free params');
+ val concl = subst_bounds (frees, Logic.strip_assums_concl rule);
+ val prems = map (curry subst_bounds frees) (Logic.strip_assums_hyp rule);
+ val rule' = Logic.list_implies (prems, concl);
+ val aprems = map (atomize_term (ProofContext.theory_of ctxt)) prems;
+ val arule = list_all_free (params', Logic.list_implies (aprems, concl));
+
+ fun check_ind err t = case dest_predicate cs params t of
+ NONE => err (bad_app ^
+ commas (map (Syntax.string_of_term ctxt) params))
+ | SOME (_, _, ys, _) =>
+ if exists (fn c => exists (fn t => Logic.occs (c, t)) ys) cs
+ then err bad_ind_occ else ();
+
+ fun check_prem' prem t =
+ if head_of t mem cs then
+ check_ind (err_in_prem ctxt err_name rule prem) t
+ else (case t of
+ Abs (_, _, t) => check_prem' prem t
+ | t $ u => (check_prem' prem t; check_prem' prem u)
+ | _ => ());
+
+ fun check_prem (prem, aprem) =
+ if can HOLogic.dest_Trueprop aprem then check_prem' prem prem
+ else err_in_prem ctxt err_name rule prem "Non-atomic premise";
+ in
+ (case concl of
+ Const ("Trueprop", _) $ t =>
+ if head_of t mem cs then
+ (check_ind (err_in_rule ctxt err_name rule') t;
+ List.app check_prem (prems ~~ aprems))
+ else err_in_rule ctxt err_name rule' bad_concl
+ | _ => err_in_rule ctxt err_name rule' bad_concl);
+ ((binding, att), arule)
+ end;
+
+val rulify =
+ hol_simplify inductive_conj
+ #> hol_simplify inductive_rulify
+ #> hol_simplify inductive_rulify_fallback
+ #> Simplifier.norm_hhf;
+
+end;
+
+
+
+(** proofs for (co)inductive predicates **)
+
+(* prove monotonicity *)
+
+fun prove_mono quiet_mode skip_mono fork_mono predT fp_fun monos ctxt =
+ (message (quiet_mode orelse skip_mono andalso !quick_and_dirty orelse fork_mono)
+ " Proving monotonicity ...";
+ (if skip_mono then SkipProof.prove else if fork_mono then Goal.prove_future else Goal.prove) ctxt
+ [] []
+ (HOLogic.mk_Trueprop
+ (Const (@{const_name Orderings.mono}, (predT --> predT) --> HOLogic.boolT) $ fp_fun))
+ (fn _ => EVERY [rtac @{thm monoI} 1,
+ REPEAT (resolve_tac [le_funI, le_boolI'] 1),
+ REPEAT (FIRST
+ [atac 1,
+ resolve_tac (List.concat (map mk_mono monos) @ get_monos ctxt) 1,
+ etac le_funE 1, dtac le_boolD 1])]));
+
+
+(* prove introduction rules *)
+
+fun prove_intrs quiet_mode coind mono fp_def k params intr_ts rec_preds_defs ctxt =
+ let
+ val _ = clean_message quiet_mode " Proving the introduction rules ...";
+
+ val unfold = funpow k (fn th => th RS fun_cong)
+ (mono RS (fp_def RS
+ (if coind then def_gfp_unfold else def_lfp_unfold)));
+
+ fun select_disj 1 1 = []
+ | select_disj _ 1 = [rtac disjI1]
+ | select_disj n i = (rtac disjI2)::(select_disj (n - 1) (i - 1));
+
+ val rules = [refl, TrueI, notFalseI, exI, conjI];
+
+ val intrs = map_index (fn (i, intr) => rulify
+ (SkipProof.prove ctxt (map (fst o dest_Free) params) [] intr (fn _ => EVERY
+ [rewrite_goals_tac rec_preds_defs,
+ rtac (unfold RS iffD2) 1,
+ EVERY1 (select_disj (length intr_ts) (i + 1)),
+ (*Not ares_tac, since refl must be tried before any equality assumptions;
+ backtracking may occur if the premises have extra variables!*)
+ DEPTH_SOLVE_1 (resolve_tac rules 1 APPEND assume_tac 1)]))) intr_ts
+
+ in (intrs, unfold) end;
+
+
+(* prove elimination rules *)
+
+fun prove_elims quiet_mode cs params intr_ts intr_names unfold rec_preds_defs ctxt =
+ let
+ val _ = clean_message quiet_mode " Proving the elimination rules ...";
+
+ val ([pname], ctxt') = ctxt |>
+ Variable.add_fixes (map (fst o dest_Free) params) |> snd |>
+ Variable.variant_fixes ["P"];
+ val P = HOLogic.mk_Trueprop (Free (pname, HOLogic.boolT));
+
+ fun dest_intr r =
+ (the (dest_predicate cs params (HOLogic.dest_Trueprop (Logic.strip_assums_concl r))),
+ Logic.strip_assums_hyp r, Logic.strip_params r);
+
+ val intrs = map dest_intr intr_ts ~~ intr_names;
+
+ val rules1 = [disjE, exE, FalseE];
+ val rules2 = [conjE, FalseE, notTrueE];
+
+ fun prove_elim c =
+ let
+ val Ts = List.drop (binder_types (fastype_of c), length params);
+ val (anames, ctxt'') = Variable.variant_fixes (mk_names "a" (length Ts)) ctxt';
+ val frees = map Free (anames ~~ Ts);
+
+ fun mk_elim_prem ((_, _, us, _), ts, params') =
+ list_all (params',
+ Logic.list_implies (map (HOLogic.mk_Trueprop o HOLogic.mk_eq)
+ (frees ~~ us) @ ts, P));
+ val c_intrs = (List.filter (equal c o #1 o #1 o #1) intrs);
+ val prems = HOLogic.mk_Trueprop (list_comb (c, params @ frees)) ::
+ map mk_elim_prem (map #1 c_intrs)
+ in
+ (SkipProof.prove ctxt'' [] prems P
+ (fn {prems, ...} => EVERY
+ [cut_facts_tac [hd prems] 1,
+ rewrite_goals_tac rec_preds_defs,
+ dtac (unfold RS iffD1) 1,
+ REPEAT (FIRSTGOAL (eresolve_tac rules1)),
+ REPEAT (FIRSTGOAL (eresolve_tac rules2)),
+ EVERY (map (fn prem =>
+ DEPTH_SOLVE_1 (ares_tac [rewrite_rule rec_preds_defs prem, conjI] 1)) (tl prems))])
+ |> rulify
+ |> singleton (ProofContext.export ctxt'' ctxt),
+ map #2 c_intrs)
+ end
+
+ in map prove_elim cs end;
+
+
+(* derivation of simplified elimination rules *)
+
+local
+
+(*delete needless equality assumptions*)
+val refl_thin = Goal.prove_global @{theory HOL} [] [] @{prop "!!P. a = a ==> P ==> P"}
+ (fn _ => assume_tac 1);
+val elim_rls = [asm_rl, FalseE, refl_thin, conjE, exE];
+val elim_tac = REPEAT o Tactic.eresolve_tac elim_rls;
+
+fun simp_case_tac ss i =
+ EVERY' [elim_tac, asm_full_simp_tac ss, elim_tac, REPEAT o bound_hyp_subst_tac] i;
+
+in
+
+fun mk_cases ctxt prop =
+ let
+ val thy = ProofContext.theory_of ctxt;
+ val ss = Simplifier.local_simpset_of ctxt;
+
+ fun err msg =
+ error (Pretty.string_of (Pretty.block
+ [Pretty.str msg, Pretty.fbrk, Syntax.pretty_term ctxt prop]));
+
+ val elims = Induct.find_casesP ctxt prop;
+
+ val cprop = Thm.cterm_of thy prop;
+ val tac = ALLGOALS (simp_case_tac ss) THEN prune_params_tac;
+ fun mk_elim rl =
+ Thm.implies_intr cprop (Tactic.rule_by_tactic tac (Thm.assume cprop RS rl))
+ |> singleton (Variable.export (Variable.auto_fixes prop ctxt) ctxt);
+ in
+ (case get_first (try mk_elim) elims of
+ SOME r => r
+ | NONE => err "Proposition not an inductive predicate:")
+ end;
+
+end;
+
+
+(* inductive_cases *)
+
+fun gen_inductive_cases prep_att prep_prop args lthy =
+ let
+ val thy = ProofContext.theory_of lthy;
+ val facts = args |> map (fn ((a, atts), props) =>
+ ((a, map (prep_att thy) atts),
+ map (Thm.no_attributes o single o mk_cases lthy o prep_prop lthy) props));
+ in lthy |> LocalTheory.notes Thm.generatedK facts |>> map snd end;
+
+val inductive_cases = gen_inductive_cases Attrib.intern_src Syntax.read_prop;
+val inductive_cases_i = gen_inductive_cases (K I) Syntax.check_prop;
+
+
+val ind_cases_setup =
+ Method.setup @{binding ind_cases}
+ (Scan.lift (Scan.repeat1 Args.name_source --
+ Scan.optional (Args.$$$ "for" |-- Scan.repeat1 Args.name) []) >>
+ (fn (raw_props, fixes) => fn ctxt =>
+ let
+ val (_, ctxt') = Variable.add_fixes fixes ctxt;
+ val props = Syntax.read_props ctxt' raw_props;
+ val ctxt'' = fold Variable.declare_term props ctxt';
+ val rules = ProofContext.export ctxt'' ctxt (map (mk_cases ctxt'') props)
+ in Method.erule 0 rules end))
+ "dynamic case analysis on predicates";
+
+
+(* prove induction rule *)
+
+fun prove_indrule quiet_mode cs argTs bs xs rec_const params intr_ts mono
+ fp_def rec_preds_defs ctxt =
+ let
+ val _ = clean_message quiet_mode " Proving the induction rule ...";
+ val thy = ProofContext.theory_of ctxt;
+
+ (* predicates for induction rule *)
+
+ val (pnames, ctxt') = ctxt |>
+ Variable.add_fixes (map (fst o dest_Free) params) |> snd |>
+ Variable.variant_fixes (mk_names "P" (length cs));
+ val preds = map Free (pnames ~~
+ map (fn c => List.drop (binder_types (fastype_of c), length params) --->
+ HOLogic.boolT) cs);
+
+ (* transform an introduction rule into a premise for induction rule *)
+
+ fun mk_ind_prem r =
+ let
+ fun subst s = (case dest_predicate cs params s of
+ SOME (_, i, ys, (_, Ts)) =>
+ let
+ val k = length Ts;
+ val bs = map Bound (k - 1 downto 0);
+ val P = list_comb (List.nth (preds, i),
+ map (incr_boundvars k) ys @ bs);
+ val Q = list_abs (mk_names "x" k ~~ Ts,
+ HOLogic.mk_binop inductive_conj_name
+ (list_comb (incr_boundvars k s, bs), P))
+ in (Q, case Ts of [] => SOME (s, P) | _ => NONE) end
+ | NONE => (case s of
+ (t $ u) => (fst (subst t) $ fst (subst u), NONE)
+ | (Abs (a, T, t)) => (Abs (a, T, fst (subst t)), NONE)
+ | _ => (s, NONE)));
+
+ fun mk_prem (s, prems) = (case subst s of
+ (_, SOME (t, u)) => t :: u :: prems
+ | (t, _) => t :: prems);
+
+ val SOME (_, i, ys, _) = dest_predicate cs params
+ (HOLogic.dest_Trueprop (Logic.strip_assums_concl r))
+
+ in list_all_free (Logic.strip_params r,
+ Logic.list_implies (map HOLogic.mk_Trueprop (List.foldr mk_prem
+ [] (map HOLogic.dest_Trueprop (Logic.strip_assums_hyp r))),
+ HOLogic.mk_Trueprop (list_comb (List.nth (preds, i), ys))))
+ end;
+
+ val ind_prems = map mk_ind_prem intr_ts;
+
+
+ (* make conclusions for induction rules *)
+
+ val Tss = map (binder_types o fastype_of) preds;
+ val (xnames, ctxt'') =
+ Variable.variant_fixes (mk_names "x" (length (flat Tss))) ctxt';
+ val mutual_ind_concl = HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
+ (map (fn (((xnames, Ts), c), P) =>
+ let val frees = map Free (xnames ~~ Ts)
+ in HOLogic.mk_imp
+ (list_comb (c, params @ frees), list_comb (P, frees))
+ end) (unflat Tss xnames ~~ Tss ~~ cs ~~ preds)));
+
+
+ (* make predicate for instantiation of abstract induction rule *)
+
+ val ind_pred = fold_rev lambda (bs @ xs) (foldr1 HOLogic.mk_conj
+ (map_index (fn (i, P) => List.foldr HOLogic.mk_imp
+ (list_comb (P, make_args' argTs xs (binder_types (fastype_of P))))
+ (make_bool_args HOLogic.mk_not I bs i)) preds));
+
+ val ind_concl = HOLogic.mk_Trueprop
+ (HOLogic.mk_binrel "HOL.ord_class.less_eq" (rec_const, ind_pred));
+
+ val raw_fp_induct = (mono RS (fp_def RS def_lfp_induct));
+
+ val induct = SkipProof.prove ctxt'' [] ind_prems ind_concl
+ (fn {prems, ...} => EVERY
+ [rewrite_goals_tac [inductive_conj_def],
+ DETERM (rtac raw_fp_induct 1),
+ REPEAT (resolve_tac [le_funI, le_boolI] 1),
+ rewrite_goals_tac (inf_fun_eq :: inf_bool_eq :: simp_thms'),
+ (*This disjE separates out the introduction rules*)
+ REPEAT (FIRSTGOAL (eresolve_tac [disjE, exE, FalseE])),
+ (*Now break down the individual cases. No disjE here in case
+ some premise involves disjunction.*)
+ REPEAT (FIRSTGOAL (etac conjE ORELSE' bound_hyp_subst_tac)),
+ REPEAT (FIRSTGOAL
+ (resolve_tac [conjI, impI] ORELSE' (etac notE THEN' atac))),
+ EVERY (map (fn prem => DEPTH_SOLVE_1 (ares_tac [rewrite_rule
+ (inductive_conj_def :: rec_preds_defs @ simp_thms') prem,
+ conjI, refl] 1)) prems)]);
+
+ val lemma = SkipProof.prove ctxt'' [] []
+ (Logic.mk_implies (ind_concl, mutual_ind_concl)) (fn _ => EVERY
+ [rewrite_goals_tac rec_preds_defs,
+ REPEAT (EVERY
+ [REPEAT (resolve_tac [conjI, impI] 1),
+ REPEAT (eresolve_tac [le_funE, le_boolE] 1),
+ atac 1,
+ rewrite_goals_tac simp_thms',
+ atac 1])])
+
+ in singleton (ProofContext.export ctxt'' ctxt) (induct RS lemma) end;
+
+
+
+(** specification of (co)inductive predicates **)
+
+fun mk_ind_def quiet_mode skip_mono fork_mono alt_name coind cs intr_ts monos params cnames_syn ctxt =
+ let
+ val fp_name = if coind then @{const_name Inductive.gfp} else @{const_name Inductive.lfp};
+
+ val argTs = fold (fn c => fn Ts => Ts @
+ (List.drop (binder_types (fastype_of c), length params) \\ Ts)) cs [];
+ val k = log 2 1 (length cs);
+ val predT = replicate k HOLogic.boolT ---> argTs ---> HOLogic.boolT;
+ val p :: xs = map Free (Variable.variant_frees ctxt intr_ts
+ (("p", predT) :: (mk_names "x" (length argTs) ~~ argTs)));
+ val bs = map Free (Variable.variant_frees ctxt (p :: xs @ intr_ts)
+ (map (rpair HOLogic.boolT) (mk_names "b" k)));
+
+ fun subst t = (case dest_predicate cs params t of
+ SOME (_, i, ts, (Ts, Us)) =>
+ let
+ val l = length Us;
+ val zs = map Bound (l - 1 downto 0)
+ in
+ list_abs (map (pair "z") Us, list_comb (p,
+ make_bool_args' bs i @ make_args argTs
+ ((map (incr_boundvars l) ts ~~ Ts) @ (zs ~~ Us))))
+ end
+ | NONE => (case t of
+ t1 $ t2 => subst t1 $ subst t2
+ | Abs (x, T, u) => Abs (x, T, subst u)
+ | _ => t));
+
+ (* transform an introduction rule into a conjunction *)
+ (* [| p_i t; ... |] ==> p_j u *)
+ (* is transformed into *)
+ (* b_j & x_j = u & p b_j t & ... *)
+
+ fun transform_rule r =
+ let
+ val SOME (_, i, ts, (Ts, _)) = dest_predicate cs params
+ (HOLogic.dest_Trueprop (Logic.strip_assums_concl r));
+ val ps = make_bool_args HOLogic.mk_not I bs i @
+ map HOLogic.mk_eq (make_args' argTs xs Ts ~~ ts) @
+ map (subst o HOLogic.dest_Trueprop)
+ (Logic.strip_assums_hyp r)
+ in List.foldr (fn ((x, T), P) => HOLogic.exists_const T $ (Abs (x, T, P)))
+ (if null ps then HOLogic.true_const else foldr1 HOLogic.mk_conj ps)
+ (Logic.strip_params r)
+ end
+
+ (* make a disjunction of all introduction rules *)
+
+ val fp_fun = fold_rev lambda (p :: bs @ xs)
+ (if null intr_ts then HOLogic.false_const
+ else foldr1 HOLogic.mk_disj (map transform_rule intr_ts));
+
+ (* add definiton of recursive predicates to theory *)
+
+ val rec_name =
+ if Binding.is_empty alt_name then
+ Binding.name (space_implode "_" (map (Binding.name_of o fst) cnames_syn))
+ else alt_name;
+
+ val ((rec_const, (_, fp_def)), ctxt') = ctxt |>
+ LocalTheory.define Thm.internalK
+ ((rec_name, case cnames_syn of [(_, syn)] => syn | _ => NoSyn),
+ (Attrib.empty_binding, fold_rev lambda params
+ (Const (fp_name, (predT --> predT) --> predT) $ fp_fun)));
+ val fp_def' = Simplifier.rewrite (HOL_basic_ss addsimps [fp_def])
+ (cterm_of (ProofContext.theory_of ctxt') (list_comb (rec_const, params)));
+ val specs = if length cs < 2 then [] else
+ map_index (fn (i, (name_mx, c)) =>
+ let
+ val Ts = List.drop (binder_types (fastype_of c), length params);
+ val xs = map Free (Variable.variant_frees ctxt intr_ts
+ (mk_names "x" (length Ts) ~~ Ts))
+ in
+ (name_mx, (Attrib.empty_binding, fold_rev lambda (params @ xs)
+ (list_comb (rec_const, params @ make_bool_args' bs i @
+ make_args argTs (xs ~~ Ts)))))
+ end) (cnames_syn ~~ cs);
+ val (consts_defs, ctxt'') = fold_map (LocalTheory.define Thm.internalK) specs ctxt';
+ val preds = (case cs of [_] => [rec_const] | _ => map #1 consts_defs);
+
+ val mono = prove_mono quiet_mode skip_mono fork_mono predT fp_fun monos ctxt'';
+ val ((_, [mono']), ctxt''') =
+ LocalTheory.note Thm.internalK (Attrib.empty_binding, [mono]) ctxt'';
+
+ in (ctxt''', rec_name, mono', fp_def', map (#2 o #2) consts_defs,
+ list_comb (rec_const, params), preds, argTs, bs, xs)
+ end;
+
+fun declare_rules kind rec_binding coind no_ind cnames intrs intr_bindings intr_atts
+ elims raw_induct ctxt =
+ let
+ val rec_name = Binding.name_of rec_binding;
+ val rec_qualified = Binding.qualify false rec_name;
+ val intr_names = map Binding.name_of intr_bindings;
+ val ind_case_names = RuleCases.case_names intr_names;
+ val induct =
+ if coind then
+ (raw_induct, [RuleCases.case_names [rec_name],
+ RuleCases.case_conclusion (rec_name, intr_names),
+ RuleCases.consumes 1, Induct.coinduct_pred (hd cnames)])
+ else if no_ind orelse length cnames > 1 then
+ (raw_induct, [ind_case_names, RuleCases.consumes 0])
+ else (raw_induct RSN (2, rev_mp), [ind_case_names, RuleCases.consumes 1]);
+
+ val (intrs', ctxt1) =
+ ctxt |>
+ LocalTheory.notes kind
+ (map rec_qualified intr_bindings ~~ intr_atts ~~ map (fn th => [([th],
+ [Attrib.internal (K (ContextRules.intro_query NONE)),
+ Attrib.internal (K Nitpick_Ind_Intro_Thms.add)])]) intrs) |>>
+ map (hd o snd);
+ val (((_, elims'), (_, [induct'])), ctxt2) =
+ ctxt1 |>
+ LocalTheory.note kind ((rec_qualified (Binding.name "intros"), []), intrs') ||>>
+ fold_map (fn (name, (elim, cases)) =>
+ LocalTheory.note kind ((Binding.qualified_name (Long_Name.qualify (Long_Name.base_name name) "cases"),
+ [Attrib.internal (K (RuleCases.case_names cases)),
+ Attrib.internal (K (RuleCases.consumes 1)),
+ Attrib.internal (K (Induct.cases_pred name)),
+ Attrib.internal (K (ContextRules.elim_query NONE))]), [elim]) #>
+ apfst (hd o snd)) (if null elims then [] else cnames ~~ elims) ||>>
+ LocalTheory.note kind
+ ((rec_qualified (Binding.name (coind_prefix coind ^ "induct")),
+ map (Attrib.internal o K) (#2 induct)), [rulify (#1 induct)]);
+
+ val ctxt3 = if no_ind orelse coind then ctxt2 else
+ let val inducts = cnames ~~ ProjectRule.projects ctxt2 (1 upto length cnames) induct'
+ in
+ ctxt2 |>
+ LocalTheory.notes kind [((rec_qualified (Binding.name "inducts"), []),
+ inducts |> map (fn (name, th) => ([th],
+ [Attrib.internal (K ind_case_names),
+ Attrib.internal (K (RuleCases.consumes 1)),
+ Attrib.internal (K (Induct.induct_pred name))])))] |> snd
+ end
+ in (intrs', elims', induct', ctxt3) end;
+
+type inductive_flags =
+ {quiet_mode: bool, verbose: bool, kind: string, alt_name: binding,
+ coind: bool, no_elim: bool, no_ind: bool, skip_mono: bool, fork_mono: bool}
+
+type add_ind_def =
+ inductive_flags ->
+ term list -> (Attrib.binding * term) list -> thm list ->
+ term list -> (binding * mixfix) list ->
+ local_theory -> inductive_result * local_theory
+
+fun add_ind_def {quiet_mode, verbose, kind, alt_name, coind, no_elim, no_ind, skip_mono, fork_mono}
+ cs intros monos params cnames_syn ctxt =
+ let
+ val _ = null cnames_syn andalso error "No inductive predicates given";
+ val names = map (Binding.name_of o fst) cnames_syn;
+ val _ = message (quiet_mode andalso not verbose)
+ ("Proofs for " ^ coind_prefix coind ^ "inductive predicate(s) " ^ commas_quote names);
+
+ val cnames = map (LocalTheory.full_name ctxt o #1) cnames_syn; (* FIXME *)
+ val ((intr_names, intr_atts), intr_ts) =
+ apfst split_list (split_list (map (check_rule ctxt cs params) intros));
+
+ val (ctxt1, rec_name, mono, fp_def, rec_preds_defs, rec_const, preds,
+ argTs, bs, xs) = mk_ind_def quiet_mode skip_mono fork_mono alt_name coind cs intr_ts
+ monos params cnames_syn ctxt;
+
+ val (intrs, unfold) = prove_intrs quiet_mode coind mono fp_def (length bs + length xs)
+ params intr_ts rec_preds_defs ctxt1;
+ val elims = if no_elim then [] else
+ prove_elims quiet_mode cs params intr_ts (map Binding.name_of intr_names)
+ unfold rec_preds_defs ctxt1;
+ val raw_induct = zero_var_indexes
+ (if no_ind then Drule.asm_rl else
+ if coind then
+ singleton (ProofContext.export
+ (snd (Variable.add_fixes (map (fst o dest_Free) params) ctxt1)) ctxt1)
+ (rotate_prems ~1 (ObjectLogic.rulify
+ (fold_rule rec_preds_defs
+ (rewrite_rule [le_fun_def, le_bool_def, sup_fun_eq, sup_bool_eq]
+ (mono RS (fp_def RS def_coinduct))))))
+ else
+ prove_indrule quiet_mode cs argTs bs xs rec_const params intr_ts mono fp_def
+ rec_preds_defs ctxt1);
+
+ val (intrs', elims', induct, ctxt2) = declare_rules kind rec_name coind no_ind
+ cnames intrs intr_names intr_atts elims raw_induct ctxt1;
+
+ val result =
+ {preds = preds,
+ intrs = intrs',
+ elims = elims',
+ raw_induct = rulify raw_induct,
+ induct = induct};
+
+ val ctxt3 = ctxt2
+ |> LocalTheory.declaration (fn phi =>
+ let val result' = morph_result phi result;
+ in put_inductives cnames (*global names!?*) ({names = cnames, coind = coind}, result') end);
+ in (result, ctxt3) end;
+
+
+(* external interfaces *)
+
+fun gen_add_inductive_i mk_def
+ (flags as {quiet_mode, verbose, kind, alt_name, coind, no_elim, no_ind, skip_mono, fork_mono})
+ cnames_syn pnames spec monos lthy =
+ let
+ val thy = ProofContext.theory_of lthy;
+ val _ = Theory.requires thy "Inductive" (coind_prefix coind ^ "inductive definitions");
+
+
+ (* abbrevs *)
+
+ val (_, ctxt1) = Variable.add_fixes (map (Binding.name_of o fst o fst) cnames_syn) lthy;
+
+ fun get_abbrev ((name, atts), t) =
+ if can (Logic.strip_assums_concl #> Logic.dest_equals) t then
+ let
+ val _ = Binding.is_empty name andalso null atts orelse
+ error "Abbreviations may not have names or attributes";
+ val ((x, T), rhs) = LocalDefs.abs_def (snd (LocalDefs.cert_def ctxt1 t));
+ val var =
+ (case find_first (fn ((c, _), _) => Binding.name_of c = x) cnames_syn of
+ NONE => error ("Undeclared head of abbreviation " ^ quote x)
+ | SOME ((b, T'), mx) =>
+ if T <> T' then error ("Bad type specification for abbreviation " ^ quote x)
+ else (b, mx));
+ in SOME (var, rhs) end
+ else NONE;
+
+ val abbrevs = map_filter get_abbrev spec;
+ val bs = map (Binding.name_of o fst o fst) abbrevs;
+
+
+ (* predicates *)
+
+ val pre_intros = filter_out (is_some o get_abbrev) spec;
+ val cnames_syn' = filter_out (member (op =) bs o Binding.name_of o fst o fst) cnames_syn;
+ val cs = map (Free o apfst Binding.name_of o fst) cnames_syn';
+ val ps = map Free pnames;
+
+ val (_, ctxt2) = lthy |> Variable.add_fixes (map (Binding.name_of o fst o fst) cnames_syn');
+ val _ = map (fn abbr => LocalDefs.fixed_abbrev abbr ctxt2) abbrevs;
+ val ctxt3 = ctxt2 |> fold (snd oo LocalDefs.fixed_abbrev) abbrevs;
+ val expand = Assumption.export_term ctxt3 lthy #> ProofContext.cert_term lthy;
+
+ fun close_rule r = list_all_free (rev (fold_aterms
+ (fn t as Free (v as (s, _)) =>
+ if Variable.is_fixed ctxt1 s orelse
+ member (op =) ps t then I else insert (op =) v
+ | _ => I) r []), r);
+
+ val intros = map (apsnd (Syntax.check_term lthy #> close_rule #> expand)) pre_intros;
+ val preds = map (fn ((c, _), mx) => (c, mx)) cnames_syn';
+ in
+ lthy
+ |> mk_def flags cs intros monos ps preds
+ ||> fold (snd oo LocalTheory.abbrev Syntax.mode_default) abbrevs
+ end;
+
+fun gen_add_inductive mk_def verbose coind cnames_syn pnames_syn intro_srcs raw_monos int lthy =
+ let
+ val ((vars, intrs), _) = lthy
+ |> ProofContext.set_mode ProofContext.mode_abbrev
+ |> Specification.read_spec (cnames_syn @ pnames_syn) intro_srcs;
+ val (cs, ps) = chop (length cnames_syn) vars;
+ val monos = Attrib.eval_thms lthy raw_monos;
+ val flags = {quiet_mode = false, verbose = verbose, kind = Thm.generatedK,
+ alt_name = Binding.empty, coind = coind, no_elim = false, no_ind = false,
+ skip_mono = false, fork_mono = not int};
+ in
+ lthy
+ |> LocalTheory.set_group (serial_string ())
+ |> gen_add_inductive_i mk_def flags cs (map (apfst Binding.name_of o fst) ps) intrs monos
+ end;
+
+val add_inductive_i = gen_add_inductive_i add_ind_def;
+val add_inductive = gen_add_inductive add_ind_def;
+
+fun add_inductive_global group flags cnames_syn pnames pre_intros monos thy =
+ let
+ val name = Sign.full_name thy (fst (fst (hd cnames_syn)));
+ val ctxt' = thy
+ |> TheoryTarget.init NONE
+ |> LocalTheory.set_group group
+ |> add_inductive_i flags cnames_syn pnames pre_intros monos |> snd
+ |> LocalTheory.exit;
+ val info = #2 (the_inductive ctxt' name);
+ in (info, ProofContext.theory_of ctxt') end;
+
+
+(* read off arities of inductive predicates from raw induction rule *)
+fun arities_of induct =
+ map (fn (_ $ t $ u) =>
+ (fst (dest_Const (head_of t)), length (snd (strip_comb u))))
+ (HOLogic.dest_conj (HOLogic.dest_Trueprop (concl_of induct)));
+
+(* read off parameters of inductive predicate from raw induction rule *)
+fun params_of induct =
+ let
+ val (_ $ t $ u :: _) =
+ HOLogic.dest_conj (HOLogic.dest_Trueprop (concl_of induct));
+ val (_, ts) = strip_comb t;
+ val (_, us) = strip_comb u
+ in
+ List.take (ts, length ts - length us)
+ end;
+
+val pname_of_intr =
+ concl_of #> HOLogic.dest_Trueprop #> head_of #> dest_Const #> fst;
+
+(* partition introduction rules according to predicate name *)
+fun gen_partition_rules f induct intros =
+ fold_rev (fn r => AList.map_entry op = (pname_of_intr (f r)) (cons r)) intros
+ (map (rpair [] o fst) (arities_of induct));
+
+val partition_rules = gen_partition_rules I;
+fun partition_rules' induct = gen_partition_rules fst induct;
+
+fun unpartition_rules intros xs =
+ fold_map (fn r => AList.map_entry_yield op = (pname_of_intr r)
+ (fn x :: xs => (x, xs)) #>> the) intros xs |> fst;
+
+(* infer order of variables in intro rules from order of quantifiers in elim rule *)
+fun infer_intro_vars elim arity intros =
+ let
+ val thy = theory_of_thm elim;
+ val _ :: cases = prems_of elim;
+ val used = map (fst o fst) (Term.add_vars (prop_of elim) []);
+ fun mtch (t, u) =
+ let
+ val params = Logic.strip_params t;
+ val vars = map (Var o apfst (rpair 0))
+ (Name.variant_list used (map fst params) ~~ map snd params);
+ val ts = map (curry subst_bounds (rev vars))
+ (List.drop (Logic.strip_assums_hyp t, arity));
+ val us = Logic.strip_imp_prems u;
+ val tab = fold (Pattern.first_order_match thy) (ts ~~ us)
+ (Vartab.empty, Vartab.empty);
+ in
+ map (Envir.subst_vars tab) vars
+ end
+ in
+ map (mtch o apsnd prop_of) (cases ~~ intros)
+ end;
+
+
+
+(** package setup **)
+
+(* setup theory *)
+
+val setup =
+ ind_cases_setup #>
+ Attrib.setup @{binding mono} (Attrib.add_del mono_add mono_del)
+ "declaration of monotonicity rule";
+
+
+(* outer syntax *)
+
+local structure P = OuterParse and K = OuterKeyword in
+
+val _ = OuterKeyword.keyword "monos";
+
+fun gen_ind_decl mk_def coind =
+ P.fixes -- P.for_fixes --
+ Scan.optional SpecParse.where_alt_specs [] --
+ Scan.optional (P.$$$ "monos" |-- P.!!! SpecParse.xthms1) []
+ >> (fn (((preds, params), specs), monos) =>
+ (snd oo gen_add_inductive mk_def true coind preds params specs monos));
+
+val ind_decl = gen_ind_decl add_ind_def;
+
+val _ = OuterSyntax.local_theory' "inductive" "define inductive predicates" K.thy_decl (ind_decl false);
+val _ = OuterSyntax.local_theory' "coinductive" "define coinductive predicates" K.thy_decl (ind_decl true);
+
+val _ =
+ OuterSyntax.local_theory "inductive_cases"
+ "create simplified instances of elimination rules (improper)" K.thy_script
+ (P.and_list1 SpecParse.specs >> (snd oo inductive_cases));
+
+end;
+
+end;
--- a/src/HOL/Tools/inductive_codegen.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/inductive_codegen.ML Fri Jun 19 21:08:07 2009 +0200
@@ -62,9 +62,9 @@
val nparms = (case optnparms of
SOME k => k
| NONE => (case rules of
- [] => (case try (InductivePackage.the_inductive (ProofContext.init thy)) s of
+ [] => (case try (Inductive.the_inductive (ProofContext.init thy)) s of
SOME (_, {raw_induct, ...}) =>
- length (InductivePackage.params_of raw_induct)
+ length (Inductive.params_of raw_induct)
| NONE => 0)
| xs => snd (snd (snd (split_last xs)))))
in CodegenData.put
@@ -81,11 +81,11 @@
fun get_clauses thy s =
let val {intros, graph, ...} = CodegenData.get thy
in case Symtab.lookup intros s of
- NONE => (case try (InductivePackage.the_inductive (ProofContext.init thy)) s of
+ NONE => (case try (Inductive.the_inductive (ProofContext.init thy)) s of
NONE => NONE
| SOME ({names, ...}, {intrs, raw_induct, ...}) =>
SOME (names, Codegen.thyname_of_const thy s,
- length (InductivePackage.params_of raw_induct),
+ length (Inductive.params_of raw_induct),
preprocess thy intrs))
| SOME _ =>
let
@@ -103,7 +103,7 @@
let
val cnstrs = List.concat (List.concat (map
(map (fn (_, (_, _, cs)) => map (apsnd length) cs) o #descr o snd)
- (Symtab.dest (DatatypePackage.get_datatypes thy))));
+ (Symtab.dest (Datatype.get_datatypes thy))));
fun check t = (case strip_comb t of
(Var _, []) => true
| (Const (s, _), ts) => (case AList.lookup (op =) cnstrs s of
--- a/src/HOL/Tools/inductive_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,968 +0,0 @@
-(* Title: HOL/Tools/inductive_package.ML
- Author: Lawrence C Paulson, Cambridge University Computer Laboratory
- Author: Stefan Berghofer and Markus Wenzel, TU Muenchen
-
-(Co)Inductive Definition module for HOL.
-
-Features:
- * least or greatest fixedpoints
- * mutually recursive definitions
- * definitions involving arbitrary monotone operators
- * automatically proves introduction and elimination rules
-
- Introduction rules have the form
- [| M Pj ti, ..., Q x, ... |] ==> Pk t
- where M is some monotone operator (usually the identity)
- Q x is any side condition on the free variables
- ti, t are any terms
- Pj, Pk are two of the predicates being defined in mutual recursion
-*)
-
-signature BASIC_INDUCTIVE_PACKAGE =
-sig
- type inductive_result
- val morph_result: morphism -> inductive_result -> inductive_result
- type inductive_info
- val the_inductive: Proof.context -> string -> inductive_info
- val print_inductives: Proof.context -> unit
- val mono_add: attribute
- val mono_del: attribute
- val get_monos: Proof.context -> thm list
- val mk_cases: Proof.context -> term -> thm
- val inductive_forall_name: string
- val inductive_forall_def: thm
- val rulify: thm -> thm
- val inductive_cases: (Attrib.binding * string list) list -> local_theory ->
- thm list list * local_theory
- val inductive_cases_i: (Attrib.binding * term list) list -> local_theory ->
- thm list list * local_theory
- type inductive_flags
- val add_inductive_i:
- inductive_flags -> ((binding * typ) * mixfix) list ->
- (string * typ) list -> (Attrib.binding * term) list -> thm list -> local_theory ->
- inductive_result * local_theory
- val add_inductive: bool -> bool ->
- (binding * string option * mixfix) list ->
- (binding * string option * mixfix) list ->
- (Attrib.binding * string) list ->
- (Facts.ref * Attrib.src list) list ->
- bool -> local_theory -> inductive_result * local_theory
- val add_inductive_global: string -> inductive_flags ->
- ((binding * typ) * mixfix) list -> (string * typ) list -> (Attrib.binding * term) list ->
- thm list -> theory -> inductive_result * theory
- val arities_of: thm -> (string * int) list
- val params_of: thm -> term list
- val partition_rules: thm -> thm list -> (string * thm list) list
- val partition_rules': thm -> (thm * 'a) list -> (string * (thm * 'a) list) list
- val unpartition_rules: thm list -> (string * 'a list) list -> 'a list
- val infer_intro_vars: thm -> int -> thm list -> term list list
- val setup: theory -> theory
-end;
-
-signature INDUCTIVE_PACKAGE =
-sig
- include BASIC_INDUCTIVE_PACKAGE
- type add_ind_def
- val declare_rules: string -> binding -> bool -> bool -> string list ->
- thm list -> binding list -> Attrib.src list list -> (thm * string list) list ->
- thm -> local_theory -> thm list * thm list * thm * local_theory
- val add_ind_def: add_ind_def
- val gen_add_inductive_i: add_ind_def -> inductive_flags ->
- ((binding * typ) * mixfix) list -> (string * typ) list -> (Attrib.binding * term) list ->
- thm list -> local_theory -> inductive_result * local_theory
- val gen_add_inductive: add_ind_def -> bool -> bool ->
- (binding * string option * mixfix) list ->
- (binding * string option * mixfix) list ->
- (Attrib.binding * string) list -> (Facts.ref * Attrib.src list) list ->
- bool -> local_theory -> inductive_result * local_theory
- val gen_ind_decl: add_ind_def -> bool ->
- OuterParse.token list -> (bool -> local_theory -> local_theory) * OuterParse.token list
-end;
-
-structure InductivePackage: INDUCTIVE_PACKAGE =
-struct
-
-
-(** theory context references **)
-
-val inductive_forall_name = "HOL.induct_forall";
-val inductive_forall_def = thm "induct_forall_def";
-val inductive_conj_name = "HOL.induct_conj";
-val inductive_conj_def = thm "induct_conj_def";
-val inductive_conj = thms "induct_conj";
-val inductive_atomize = thms "induct_atomize";
-val inductive_rulify = thms "induct_rulify";
-val inductive_rulify_fallback = thms "induct_rulify_fallback";
-
-val notTrueE = TrueI RSN (2, notE);
-val notFalseI = Seq.hd (atac 1 notI);
-val simp_thms' = map (fn s => mk_meta_eq (the (find_first
- (equal (OldGoals.read_prop @{theory HOL} s) o prop_of) simp_thms)))
- ["(~True) = False", "(~False) = True",
- "(True --> ?P) = ?P", "(False --> ?P) = True",
- "(?P & True) = ?P", "(True & ?P) = ?P"];
-
-
-
-(** context data **)
-
-type inductive_result =
- {preds: term list, elims: thm list, raw_induct: thm,
- induct: thm, intrs: thm list};
-
-fun morph_result phi {preds, elims, raw_induct: thm, induct, intrs} =
- let
- val term = Morphism.term phi;
- val thm = Morphism.thm phi;
- val fact = Morphism.fact phi;
- in
- {preds = map term preds, elims = fact elims, raw_induct = thm raw_induct,
- induct = thm induct, intrs = fact intrs}
- end;
-
-type inductive_info =
- {names: string list, coind: bool} * inductive_result;
-
-structure InductiveData = GenericDataFun
-(
- type T = inductive_info Symtab.table * thm list;
- val empty = (Symtab.empty, []);
- val extend = I;
- fun merge _ ((tab1, monos1), (tab2, monos2)) =
- (Symtab.merge (K true) (tab1, tab2), Thm.merge_thms (monos1, monos2));
-);
-
-val get_inductives = InductiveData.get o Context.Proof;
-
-fun print_inductives ctxt =
- let
- val (tab, monos) = get_inductives ctxt;
- val space = Consts.space_of (ProofContext.consts_of ctxt);
- in
- [Pretty.strs ("(co)inductives:" :: map #1 (NameSpace.extern_table (space, tab))),
- Pretty.big_list "monotonicity rules:" (map (ProofContext.pretty_thm ctxt) monos)]
- |> Pretty.chunks |> Pretty.writeln
- end;
-
-
-(* get and put data *)
-
-fun the_inductive ctxt name =
- (case Symtab.lookup (#1 (get_inductives ctxt)) name of
- NONE => error ("Unknown (co)inductive predicate " ^ quote name)
- | SOME info => info);
-
-fun put_inductives names info = InductiveData.map
- (apfst (fold (fn name => Symtab.update (name, info)) names));
-
-
-
-(** monotonicity rules **)
-
-val get_monos = #2 o get_inductives;
-val map_monos = InductiveData.map o apsnd;
-
-fun mk_mono thm =
- let
- val concl = concl_of thm;
- fun eq2mono thm' = [thm' RS (thm' RS eq_to_mono)] @
- (case concl of
- (_ $ (_ $ (Const ("Not", _) $ _) $ _)) => []
- | _ => [thm' RS (thm' RS eq_to_mono2)]);
- fun dest_less_concl thm = dest_less_concl (thm RS le_funD)
- handle THM _ => thm RS le_boolD
- in
- case concl of
- Const ("==", _) $ _ $ _ => eq2mono (thm RS meta_eq_to_obj_eq)
- | _ $ (Const ("op =", _) $ _ $ _) => eq2mono thm
- | _ $ (Const ("HOL.ord_class.less_eq", _) $ _ $ _) =>
- [dest_less_concl (Seq.hd (REPEAT (FIRSTGOAL
- (resolve_tac [le_funI, le_boolI'])) thm))]
- | _ => [thm]
- end handle THM _ => error ("Bad monotonicity theorem:\n" ^ Display.string_of_thm thm);
-
-val mono_add = Thm.declaration_attribute (map_monos o fold Thm.add_thm o mk_mono);
-val mono_del = Thm.declaration_attribute (map_monos o fold Thm.del_thm o mk_mono);
-
-
-
-(** misc utilities **)
-
-fun message quiet_mode s = if quiet_mode then () else writeln s;
-fun clean_message quiet_mode s = if ! quick_and_dirty then () else message quiet_mode s;
-
-fun coind_prefix true = "co"
- | coind_prefix false = "";
-
-fun log (b:int) m n = if m >= n then 0 else 1 + log b (b * m) n;
-
-fun make_bool_args f g [] i = []
- | make_bool_args f g (x :: xs) i =
- (if i mod 2 = 0 then f x else g x) :: make_bool_args f g xs (i div 2);
-
-fun make_bool_args' xs =
- make_bool_args (K HOLogic.false_const) (K HOLogic.true_const) xs;
-
-fun find_arg T x [] = sys_error "find_arg"
- | find_arg T x ((p as (_, (SOME _, _))) :: ps) =
- apsnd (cons p) (find_arg T x ps)
- | find_arg T x ((p as (U, (NONE, y))) :: ps) =
- if (T: typ) = U then (y, (U, (SOME x, y)) :: ps)
- else apsnd (cons p) (find_arg T x ps);
-
-fun make_args Ts xs =
- map (fn (T, (NONE, ())) => Const (@{const_name undefined}, T) | (_, (SOME t, ())) => t)
- (fold (fn (t, T) => snd o find_arg T t) xs (map (rpair (NONE, ())) Ts));
-
-fun make_args' Ts xs Us =
- fst (fold_map (fn T => find_arg T ()) Us (Ts ~~ map (pair NONE) xs));
-
-fun dest_predicate cs params t =
- let
- val k = length params;
- val (c, ts) = strip_comb t;
- val (xs, ys) = chop k ts;
- val i = find_index_eq c cs;
- in
- if xs = params andalso i >= 0 then
- SOME (c, i, ys, chop (length ys)
- (List.drop (binder_types (fastype_of c), k)))
- else NONE
- end;
-
-fun mk_names a 0 = []
- | mk_names a 1 = [a]
- | mk_names a n = map (fn i => a ^ string_of_int i) (1 upto n);
-
-
-
-(** process rules **)
-
-local
-
-fun err_in_rule ctxt name t msg =
- error (cat_lines ["Ill-formed introduction rule " ^ quote name,
- Syntax.string_of_term ctxt t, msg]);
-
-fun err_in_prem ctxt name t p msg =
- error (cat_lines ["Ill-formed premise", Syntax.string_of_term ctxt p,
- "in introduction rule " ^ quote name, Syntax.string_of_term ctxt t, msg]);
-
-val bad_concl = "Conclusion of introduction rule must be an inductive predicate";
-
-val bad_ind_occ = "Inductive predicate occurs in argument of inductive predicate";
-
-val bad_app = "Inductive predicate must be applied to parameter(s) ";
-
-fun atomize_term thy = MetaSimplifier.rewrite_term thy inductive_atomize [];
-
-in
-
-fun check_rule ctxt cs params ((binding, att), rule) =
- let
- val err_name = Binding.str_of binding;
- val params' = Term.variant_frees rule (Logic.strip_params rule);
- val frees = rev (map Free params');
- val concl = subst_bounds (frees, Logic.strip_assums_concl rule);
- val prems = map (curry subst_bounds frees) (Logic.strip_assums_hyp rule);
- val rule' = Logic.list_implies (prems, concl);
- val aprems = map (atomize_term (ProofContext.theory_of ctxt)) prems;
- val arule = list_all_free (params', Logic.list_implies (aprems, concl));
-
- fun check_ind err t = case dest_predicate cs params t of
- NONE => err (bad_app ^
- commas (map (Syntax.string_of_term ctxt) params))
- | SOME (_, _, ys, _) =>
- if exists (fn c => exists (fn t => Logic.occs (c, t)) ys) cs
- then err bad_ind_occ else ();
-
- fun check_prem' prem t =
- if head_of t mem cs then
- check_ind (err_in_prem ctxt err_name rule prem) t
- else (case t of
- Abs (_, _, t) => check_prem' prem t
- | t $ u => (check_prem' prem t; check_prem' prem u)
- | _ => ());
-
- fun check_prem (prem, aprem) =
- if can HOLogic.dest_Trueprop aprem then check_prem' prem prem
- else err_in_prem ctxt err_name rule prem "Non-atomic premise";
- in
- (case concl of
- Const ("Trueprop", _) $ t =>
- if head_of t mem cs then
- (check_ind (err_in_rule ctxt err_name rule') t;
- List.app check_prem (prems ~~ aprems))
- else err_in_rule ctxt err_name rule' bad_concl
- | _ => err_in_rule ctxt err_name rule' bad_concl);
- ((binding, att), arule)
- end;
-
-val rulify =
- hol_simplify inductive_conj
- #> hol_simplify inductive_rulify
- #> hol_simplify inductive_rulify_fallback
- #> Simplifier.norm_hhf;
-
-end;
-
-
-
-(** proofs for (co)inductive predicates **)
-
-(* prove monotonicity *)
-
-fun prove_mono quiet_mode skip_mono fork_mono predT fp_fun monos ctxt =
- (message (quiet_mode orelse skip_mono andalso !quick_and_dirty orelse fork_mono)
- " Proving monotonicity ...";
- (if skip_mono then SkipProof.prove else if fork_mono then Goal.prove_future else Goal.prove) ctxt
- [] []
- (HOLogic.mk_Trueprop
- (Const (@{const_name Orderings.mono}, (predT --> predT) --> HOLogic.boolT) $ fp_fun))
- (fn _ => EVERY [rtac @{thm monoI} 1,
- REPEAT (resolve_tac [le_funI, le_boolI'] 1),
- REPEAT (FIRST
- [atac 1,
- resolve_tac (List.concat (map mk_mono monos) @ get_monos ctxt) 1,
- etac le_funE 1, dtac le_boolD 1])]));
-
-
-(* prove introduction rules *)
-
-fun prove_intrs quiet_mode coind mono fp_def k params intr_ts rec_preds_defs ctxt =
- let
- val _ = clean_message quiet_mode " Proving the introduction rules ...";
-
- val unfold = funpow k (fn th => th RS fun_cong)
- (mono RS (fp_def RS
- (if coind then def_gfp_unfold else def_lfp_unfold)));
-
- fun select_disj 1 1 = []
- | select_disj _ 1 = [rtac disjI1]
- | select_disj n i = (rtac disjI2)::(select_disj (n - 1) (i - 1));
-
- val rules = [refl, TrueI, notFalseI, exI, conjI];
-
- val intrs = map_index (fn (i, intr) => rulify
- (SkipProof.prove ctxt (map (fst o dest_Free) params) [] intr (fn _ => EVERY
- [rewrite_goals_tac rec_preds_defs,
- rtac (unfold RS iffD2) 1,
- EVERY1 (select_disj (length intr_ts) (i + 1)),
- (*Not ares_tac, since refl must be tried before any equality assumptions;
- backtracking may occur if the premises have extra variables!*)
- DEPTH_SOLVE_1 (resolve_tac rules 1 APPEND assume_tac 1)]))) intr_ts
-
- in (intrs, unfold) end;
-
-
-(* prove elimination rules *)
-
-fun prove_elims quiet_mode cs params intr_ts intr_names unfold rec_preds_defs ctxt =
- let
- val _ = clean_message quiet_mode " Proving the elimination rules ...";
-
- val ([pname], ctxt') = ctxt |>
- Variable.add_fixes (map (fst o dest_Free) params) |> snd |>
- Variable.variant_fixes ["P"];
- val P = HOLogic.mk_Trueprop (Free (pname, HOLogic.boolT));
-
- fun dest_intr r =
- (the (dest_predicate cs params (HOLogic.dest_Trueprop (Logic.strip_assums_concl r))),
- Logic.strip_assums_hyp r, Logic.strip_params r);
-
- val intrs = map dest_intr intr_ts ~~ intr_names;
-
- val rules1 = [disjE, exE, FalseE];
- val rules2 = [conjE, FalseE, notTrueE];
-
- fun prove_elim c =
- let
- val Ts = List.drop (binder_types (fastype_of c), length params);
- val (anames, ctxt'') = Variable.variant_fixes (mk_names "a" (length Ts)) ctxt';
- val frees = map Free (anames ~~ Ts);
-
- fun mk_elim_prem ((_, _, us, _), ts, params') =
- list_all (params',
- Logic.list_implies (map (HOLogic.mk_Trueprop o HOLogic.mk_eq)
- (frees ~~ us) @ ts, P));
- val c_intrs = (List.filter (equal c o #1 o #1 o #1) intrs);
- val prems = HOLogic.mk_Trueprop (list_comb (c, params @ frees)) ::
- map mk_elim_prem (map #1 c_intrs)
- in
- (SkipProof.prove ctxt'' [] prems P
- (fn {prems, ...} => EVERY
- [cut_facts_tac [hd prems] 1,
- rewrite_goals_tac rec_preds_defs,
- dtac (unfold RS iffD1) 1,
- REPEAT (FIRSTGOAL (eresolve_tac rules1)),
- REPEAT (FIRSTGOAL (eresolve_tac rules2)),
- EVERY (map (fn prem =>
- DEPTH_SOLVE_1 (ares_tac [rewrite_rule rec_preds_defs prem, conjI] 1)) (tl prems))])
- |> rulify
- |> singleton (ProofContext.export ctxt'' ctxt),
- map #2 c_intrs)
- end
-
- in map prove_elim cs end;
-
-
-(* derivation of simplified elimination rules *)
-
-local
-
-(*delete needless equality assumptions*)
-val refl_thin = Goal.prove_global @{theory HOL} [] [] @{prop "!!P. a = a ==> P ==> P"}
- (fn _ => assume_tac 1);
-val elim_rls = [asm_rl, FalseE, refl_thin, conjE, exE];
-val elim_tac = REPEAT o Tactic.eresolve_tac elim_rls;
-
-fun simp_case_tac ss i =
- EVERY' [elim_tac, asm_full_simp_tac ss, elim_tac, REPEAT o bound_hyp_subst_tac] i;
-
-in
-
-fun mk_cases ctxt prop =
- let
- val thy = ProofContext.theory_of ctxt;
- val ss = Simplifier.local_simpset_of ctxt;
-
- fun err msg =
- error (Pretty.string_of (Pretty.block
- [Pretty.str msg, Pretty.fbrk, Syntax.pretty_term ctxt prop]));
-
- val elims = Induct.find_casesP ctxt prop;
-
- val cprop = Thm.cterm_of thy prop;
- val tac = ALLGOALS (simp_case_tac ss) THEN prune_params_tac;
- fun mk_elim rl =
- Thm.implies_intr cprop (Tactic.rule_by_tactic tac (Thm.assume cprop RS rl))
- |> singleton (Variable.export (Variable.auto_fixes prop ctxt) ctxt);
- in
- (case get_first (try mk_elim) elims of
- SOME r => r
- | NONE => err "Proposition not an inductive predicate:")
- end;
-
-end;
-
-
-(* inductive_cases *)
-
-fun gen_inductive_cases prep_att prep_prop args lthy =
- let
- val thy = ProofContext.theory_of lthy;
- val facts = args |> map (fn ((a, atts), props) =>
- ((a, map (prep_att thy) atts),
- map (Thm.no_attributes o single o mk_cases lthy o prep_prop lthy) props));
- in lthy |> LocalTheory.notes Thm.generatedK facts |>> map snd end;
-
-val inductive_cases = gen_inductive_cases Attrib.intern_src Syntax.read_prop;
-val inductive_cases_i = gen_inductive_cases (K I) Syntax.check_prop;
-
-
-val ind_cases_setup =
- Method.setup @{binding ind_cases}
- (Scan.lift (Scan.repeat1 Args.name_source --
- Scan.optional (Args.$$$ "for" |-- Scan.repeat1 Args.name) []) >>
- (fn (raw_props, fixes) => fn ctxt =>
- let
- val (_, ctxt') = Variable.add_fixes fixes ctxt;
- val props = Syntax.read_props ctxt' raw_props;
- val ctxt'' = fold Variable.declare_term props ctxt';
- val rules = ProofContext.export ctxt'' ctxt (map (mk_cases ctxt'') props)
- in Method.erule 0 rules end))
- "dynamic case analysis on predicates";
-
-
-(* prove induction rule *)
-
-fun prove_indrule quiet_mode cs argTs bs xs rec_const params intr_ts mono
- fp_def rec_preds_defs ctxt =
- let
- val _ = clean_message quiet_mode " Proving the induction rule ...";
- val thy = ProofContext.theory_of ctxt;
-
- (* predicates for induction rule *)
-
- val (pnames, ctxt') = ctxt |>
- Variable.add_fixes (map (fst o dest_Free) params) |> snd |>
- Variable.variant_fixes (mk_names "P" (length cs));
- val preds = map Free (pnames ~~
- map (fn c => List.drop (binder_types (fastype_of c), length params) --->
- HOLogic.boolT) cs);
-
- (* transform an introduction rule into a premise for induction rule *)
-
- fun mk_ind_prem r =
- let
- fun subst s = (case dest_predicate cs params s of
- SOME (_, i, ys, (_, Ts)) =>
- let
- val k = length Ts;
- val bs = map Bound (k - 1 downto 0);
- val P = list_comb (List.nth (preds, i),
- map (incr_boundvars k) ys @ bs);
- val Q = list_abs (mk_names "x" k ~~ Ts,
- HOLogic.mk_binop inductive_conj_name
- (list_comb (incr_boundvars k s, bs), P))
- in (Q, case Ts of [] => SOME (s, P) | _ => NONE) end
- | NONE => (case s of
- (t $ u) => (fst (subst t) $ fst (subst u), NONE)
- | (Abs (a, T, t)) => (Abs (a, T, fst (subst t)), NONE)
- | _ => (s, NONE)));
-
- fun mk_prem (s, prems) = (case subst s of
- (_, SOME (t, u)) => t :: u :: prems
- | (t, _) => t :: prems);
-
- val SOME (_, i, ys, _) = dest_predicate cs params
- (HOLogic.dest_Trueprop (Logic.strip_assums_concl r))
-
- in list_all_free (Logic.strip_params r,
- Logic.list_implies (map HOLogic.mk_Trueprop (List.foldr mk_prem
- [] (map HOLogic.dest_Trueprop (Logic.strip_assums_hyp r))),
- HOLogic.mk_Trueprop (list_comb (List.nth (preds, i), ys))))
- end;
-
- val ind_prems = map mk_ind_prem intr_ts;
-
-
- (* make conclusions for induction rules *)
-
- val Tss = map (binder_types o fastype_of) preds;
- val (xnames, ctxt'') =
- Variable.variant_fixes (mk_names "x" (length (flat Tss))) ctxt';
- val mutual_ind_concl = HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
- (map (fn (((xnames, Ts), c), P) =>
- let val frees = map Free (xnames ~~ Ts)
- in HOLogic.mk_imp
- (list_comb (c, params @ frees), list_comb (P, frees))
- end) (unflat Tss xnames ~~ Tss ~~ cs ~~ preds)));
-
-
- (* make predicate for instantiation of abstract induction rule *)
-
- val ind_pred = fold_rev lambda (bs @ xs) (foldr1 HOLogic.mk_conj
- (map_index (fn (i, P) => List.foldr HOLogic.mk_imp
- (list_comb (P, make_args' argTs xs (binder_types (fastype_of P))))
- (make_bool_args HOLogic.mk_not I bs i)) preds));
-
- val ind_concl = HOLogic.mk_Trueprop
- (HOLogic.mk_binrel "HOL.ord_class.less_eq" (rec_const, ind_pred));
-
- val raw_fp_induct = (mono RS (fp_def RS def_lfp_induct));
-
- val induct = SkipProof.prove ctxt'' [] ind_prems ind_concl
- (fn {prems, ...} => EVERY
- [rewrite_goals_tac [inductive_conj_def],
- DETERM (rtac raw_fp_induct 1),
- REPEAT (resolve_tac [le_funI, le_boolI] 1),
- rewrite_goals_tac (inf_fun_eq :: inf_bool_eq :: simp_thms'),
- (*This disjE separates out the introduction rules*)
- REPEAT (FIRSTGOAL (eresolve_tac [disjE, exE, FalseE])),
- (*Now break down the individual cases. No disjE here in case
- some premise involves disjunction.*)
- REPEAT (FIRSTGOAL (etac conjE ORELSE' bound_hyp_subst_tac)),
- REPEAT (FIRSTGOAL
- (resolve_tac [conjI, impI] ORELSE' (etac notE THEN' atac))),
- EVERY (map (fn prem => DEPTH_SOLVE_1 (ares_tac [rewrite_rule
- (inductive_conj_def :: rec_preds_defs @ simp_thms') prem,
- conjI, refl] 1)) prems)]);
-
- val lemma = SkipProof.prove ctxt'' [] []
- (Logic.mk_implies (ind_concl, mutual_ind_concl)) (fn _ => EVERY
- [rewrite_goals_tac rec_preds_defs,
- REPEAT (EVERY
- [REPEAT (resolve_tac [conjI, impI] 1),
- REPEAT (eresolve_tac [le_funE, le_boolE] 1),
- atac 1,
- rewrite_goals_tac simp_thms',
- atac 1])])
-
- in singleton (ProofContext.export ctxt'' ctxt) (induct RS lemma) end;
-
-
-
-(** specification of (co)inductive predicates **)
-
-fun mk_ind_def quiet_mode skip_mono fork_mono alt_name coind cs intr_ts monos params cnames_syn ctxt =
- let
- val fp_name = if coind then @{const_name Inductive.gfp} else @{const_name Inductive.lfp};
-
- val argTs = fold (fn c => fn Ts => Ts @
- (List.drop (binder_types (fastype_of c), length params) \\ Ts)) cs [];
- val k = log 2 1 (length cs);
- val predT = replicate k HOLogic.boolT ---> argTs ---> HOLogic.boolT;
- val p :: xs = map Free (Variable.variant_frees ctxt intr_ts
- (("p", predT) :: (mk_names "x" (length argTs) ~~ argTs)));
- val bs = map Free (Variable.variant_frees ctxt (p :: xs @ intr_ts)
- (map (rpair HOLogic.boolT) (mk_names "b" k)));
-
- fun subst t = (case dest_predicate cs params t of
- SOME (_, i, ts, (Ts, Us)) =>
- let
- val l = length Us;
- val zs = map Bound (l - 1 downto 0)
- in
- list_abs (map (pair "z") Us, list_comb (p,
- make_bool_args' bs i @ make_args argTs
- ((map (incr_boundvars l) ts ~~ Ts) @ (zs ~~ Us))))
- end
- | NONE => (case t of
- t1 $ t2 => subst t1 $ subst t2
- | Abs (x, T, u) => Abs (x, T, subst u)
- | _ => t));
-
- (* transform an introduction rule into a conjunction *)
- (* [| p_i t; ... |] ==> p_j u *)
- (* is transformed into *)
- (* b_j & x_j = u & p b_j t & ... *)
-
- fun transform_rule r =
- let
- val SOME (_, i, ts, (Ts, _)) = dest_predicate cs params
- (HOLogic.dest_Trueprop (Logic.strip_assums_concl r));
- val ps = make_bool_args HOLogic.mk_not I bs i @
- map HOLogic.mk_eq (make_args' argTs xs Ts ~~ ts) @
- map (subst o HOLogic.dest_Trueprop)
- (Logic.strip_assums_hyp r)
- in List.foldr (fn ((x, T), P) => HOLogic.exists_const T $ (Abs (x, T, P)))
- (if null ps then HOLogic.true_const else foldr1 HOLogic.mk_conj ps)
- (Logic.strip_params r)
- end
-
- (* make a disjunction of all introduction rules *)
-
- val fp_fun = fold_rev lambda (p :: bs @ xs)
- (if null intr_ts then HOLogic.false_const
- else foldr1 HOLogic.mk_disj (map transform_rule intr_ts));
-
- (* add definiton of recursive predicates to theory *)
-
- val rec_name =
- if Binding.is_empty alt_name then
- Binding.name (space_implode "_" (map (Binding.name_of o fst) cnames_syn))
- else alt_name;
-
- val ((rec_const, (_, fp_def)), ctxt') = ctxt |>
- LocalTheory.define Thm.internalK
- ((rec_name, case cnames_syn of [(_, syn)] => syn | _ => NoSyn),
- (Attrib.empty_binding, fold_rev lambda params
- (Const (fp_name, (predT --> predT) --> predT) $ fp_fun)));
- val fp_def' = Simplifier.rewrite (HOL_basic_ss addsimps [fp_def])
- (cterm_of (ProofContext.theory_of ctxt') (list_comb (rec_const, params)));
- val specs = if length cs < 2 then [] else
- map_index (fn (i, (name_mx, c)) =>
- let
- val Ts = List.drop (binder_types (fastype_of c), length params);
- val xs = map Free (Variable.variant_frees ctxt intr_ts
- (mk_names "x" (length Ts) ~~ Ts))
- in
- (name_mx, (Attrib.empty_binding, fold_rev lambda (params @ xs)
- (list_comb (rec_const, params @ make_bool_args' bs i @
- make_args argTs (xs ~~ Ts)))))
- end) (cnames_syn ~~ cs);
- val (consts_defs, ctxt'') = fold_map (LocalTheory.define Thm.internalK) specs ctxt';
- val preds = (case cs of [_] => [rec_const] | _ => map #1 consts_defs);
-
- val mono = prove_mono quiet_mode skip_mono fork_mono predT fp_fun monos ctxt'';
- val ((_, [mono']), ctxt''') =
- LocalTheory.note Thm.internalK (Attrib.empty_binding, [mono]) ctxt'';
-
- in (ctxt''', rec_name, mono', fp_def', map (#2 o #2) consts_defs,
- list_comb (rec_const, params), preds, argTs, bs, xs)
- end;
-
-fun declare_rules kind rec_binding coind no_ind cnames intrs intr_bindings intr_atts
- elims raw_induct ctxt =
- let
- val rec_name = Binding.name_of rec_binding;
- val rec_qualified = Binding.qualify false rec_name;
- val intr_names = map Binding.name_of intr_bindings;
- val ind_case_names = RuleCases.case_names intr_names;
- val induct =
- if coind then
- (raw_induct, [RuleCases.case_names [rec_name],
- RuleCases.case_conclusion (rec_name, intr_names),
- RuleCases.consumes 1, Induct.coinduct_pred (hd cnames)])
- else if no_ind orelse length cnames > 1 then
- (raw_induct, [ind_case_names, RuleCases.consumes 0])
- else (raw_induct RSN (2, rev_mp), [ind_case_names, RuleCases.consumes 1]);
-
- val (intrs', ctxt1) =
- ctxt |>
- LocalTheory.notes kind
- (map rec_qualified intr_bindings ~~ intr_atts ~~ map (fn th => [([th],
- [Attrib.internal (K (ContextRules.intro_query NONE)),
- Attrib.internal (K Nitpick_Ind_Intro_Thms.add)])]) intrs) |>>
- map (hd o snd);
- val (((_, elims'), (_, [induct'])), ctxt2) =
- ctxt1 |>
- LocalTheory.note kind ((rec_qualified (Binding.name "intros"), []), intrs') ||>>
- fold_map (fn (name, (elim, cases)) =>
- LocalTheory.note kind ((Binding.qualified_name (Long_Name.qualify (Long_Name.base_name name) "cases"),
- [Attrib.internal (K (RuleCases.case_names cases)),
- Attrib.internal (K (RuleCases.consumes 1)),
- Attrib.internal (K (Induct.cases_pred name)),
- Attrib.internal (K (ContextRules.elim_query NONE))]), [elim]) #>
- apfst (hd o snd)) (if null elims then [] else cnames ~~ elims) ||>>
- LocalTheory.note kind
- ((rec_qualified (Binding.name (coind_prefix coind ^ "induct")),
- map (Attrib.internal o K) (#2 induct)), [rulify (#1 induct)]);
-
- val ctxt3 = if no_ind orelse coind then ctxt2 else
- let val inducts = cnames ~~ ProjectRule.projects ctxt2 (1 upto length cnames) induct'
- in
- ctxt2 |>
- LocalTheory.notes kind [((rec_qualified (Binding.name "inducts"), []),
- inducts |> map (fn (name, th) => ([th],
- [Attrib.internal (K ind_case_names),
- Attrib.internal (K (RuleCases.consumes 1)),
- Attrib.internal (K (Induct.induct_pred name))])))] |> snd
- end
- in (intrs', elims', induct', ctxt3) end;
-
-type inductive_flags =
- {quiet_mode: bool, verbose: bool, kind: string, alt_name: binding,
- coind: bool, no_elim: bool, no_ind: bool, skip_mono: bool, fork_mono: bool}
-
-type add_ind_def =
- inductive_flags ->
- term list -> (Attrib.binding * term) list -> thm list ->
- term list -> (binding * mixfix) list ->
- local_theory -> inductive_result * local_theory
-
-fun add_ind_def {quiet_mode, verbose, kind, alt_name, coind, no_elim, no_ind, skip_mono, fork_mono}
- cs intros monos params cnames_syn ctxt =
- let
- val _ = null cnames_syn andalso error "No inductive predicates given";
- val names = map (Binding.name_of o fst) cnames_syn;
- val _ = message (quiet_mode andalso not verbose)
- ("Proofs for " ^ coind_prefix coind ^ "inductive predicate(s) " ^ commas_quote names);
-
- val cnames = map (LocalTheory.full_name ctxt o #1) cnames_syn; (* FIXME *)
- val ((intr_names, intr_atts), intr_ts) =
- apfst split_list (split_list (map (check_rule ctxt cs params) intros));
-
- val (ctxt1, rec_name, mono, fp_def, rec_preds_defs, rec_const, preds,
- argTs, bs, xs) = mk_ind_def quiet_mode skip_mono fork_mono alt_name coind cs intr_ts
- monos params cnames_syn ctxt;
-
- val (intrs, unfold) = prove_intrs quiet_mode coind mono fp_def (length bs + length xs)
- params intr_ts rec_preds_defs ctxt1;
- val elims = if no_elim then [] else
- prove_elims quiet_mode cs params intr_ts (map Binding.name_of intr_names)
- unfold rec_preds_defs ctxt1;
- val raw_induct = zero_var_indexes
- (if no_ind then Drule.asm_rl else
- if coind then
- singleton (ProofContext.export
- (snd (Variable.add_fixes (map (fst o dest_Free) params) ctxt1)) ctxt1)
- (rotate_prems ~1 (ObjectLogic.rulify
- (fold_rule rec_preds_defs
- (rewrite_rule [le_fun_def, le_bool_def, sup_fun_eq, sup_bool_eq]
- (mono RS (fp_def RS def_coinduct))))))
- else
- prove_indrule quiet_mode cs argTs bs xs rec_const params intr_ts mono fp_def
- rec_preds_defs ctxt1);
-
- val (intrs', elims', induct, ctxt2) = declare_rules kind rec_name coind no_ind
- cnames intrs intr_names intr_atts elims raw_induct ctxt1;
-
- val result =
- {preds = preds,
- intrs = intrs',
- elims = elims',
- raw_induct = rulify raw_induct,
- induct = induct};
-
- val ctxt3 = ctxt2
- |> LocalTheory.declaration (fn phi =>
- let val result' = morph_result phi result;
- in put_inductives cnames (*global names!?*) ({names = cnames, coind = coind}, result') end);
- in (result, ctxt3) end;
-
-
-(* external interfaces *)
-
-fun gen_add_inductive_i mk_def
- (flags as {quiet_mode, verbose, kind, alt_name, coind, no_elim, no_ind, skip_mono, fork_mono})
- cnames_syn pnames spec monos lthy =
- let
- val thy = ProofContext.theory_of lthy;
- val _ = Theory.requires thy "Inductive" (coind_prefix coind ^ "inductive definitions");
-
-
- (* abbrevs *)
-
- val (_, ctxt1) = Variable.add_fixes (map (Binding.name_of o fst o fst) cnames_syn) lthy;
-
- fun get_abbrev ((name, atts), t) =
- if can (Logic.strip_assums_concl #> Logic.dest_equals) t then
- let
- val _ = Binding.is_empty name andalso null atts orelse
- error "Abbreviations may not have names or attributes";
- val ((x, T), rhs) = LocalDefs.abs_def (snd (LocalDefs.cert_def ctxt1 t));
- val var =
- (case find_first (fn ((c, _), _) => Binding.name_of c = x) cnames_syn of
- NONE => error ("Undeclared head of abbreviation " ^ quote x)
- | SOME ((b, T'), mx) =>
- if T <> T' then error ("Bad type specification for abbreviation " ^ quote x)
- else (b, mx));
- in SOME (var, rhs) end
- else NONE;
-
- val abbrevs = map_filter get_abbrev spec;
- val bs = map (Binding.name_of o fst o fst) abbrevs;
-
-
- (* predicates *)
-
- val pre_intros = filter_out (is_some o get_abbrev) spec;
- val cnames_syn' = filter_out (member (op =) bs o Binding.name_of o fst o fst) cnames_syn;
- val cs = map (Free o apfst Binding.name_of o fst) cnames_syn';
- val ps = map Free pnames;
-
- val (_, ctxt2) = lthy |> Variable.add_fixes (map (Binding.name_of o fst o fst) cnames_syn');
- val _ = map (fn abbr => LocalDefs.fixed_abbrev abbr ctxt2) abbrevs;
- val ctxt3 = ctxt2 |> fold (snd oo LocalDefs.fixed_abbrev) abbrevs;
- val expand = Assumption.export_term ctxt3 lthy #> ProofContext.cert_term lthy;
-
- fun close_rule r = list_all_free (rev (fold_aterms
- (fn t as Free (v as (s, _)) =>
- if Variable.is_fixed ctxt1 s orelse
- member (op =) ps t then I else insert (op =) v
- | _ => I) r []), r);
-
- val intros = map (apsnd (Syntax.check_term lthy #> close_rule #> expand)) pre_intros;
- val preds = map (fn ((c, _), mx) => (c, mx)) cnames_syn';
- in
- lthy
- |> mk_def flags cs intros monos ps preds
- ||> fold (snd oo LocalTheory.abbrev Syntax.mode_default) abbrevs
- end;
-
-fun gen_add_inductive mk_def verbose coind cnames_syn pnames_syn intro_srcs raw_monos int lthy =
- let
- val ((vars, intrs), _) = lthy
- |> ProofContext.set_mode ProofContext.mode_abbrev
- |> Specification.read_spec (cnames_syn @ pnames_syn) intro_srcs;
- val (cs, ps) = chop (length cnames_syn) vars;
- val monos = Attrib.eval_thms lthy raw_monos;
- val flags = {quiet_mode = false, verbose = verbose, kind = Thm.generatedK,
- alt_name = Binding.empty, coind = coind, no_elim = false, no_ind = false,
- skip_mono = false, fork_mono = not int};
- in
- lthy
- |> LocalTheory.set_group (serial_string ())
- |> gen_add_inductive_i mk_def flags cs (map (apfst Binding.name_of o fst) ps) intrs monos
- end;
-
-val add_inductive_i = gen_add_inductive_i add_ind_def;
-val add_inductive = gen_add_inductive add_ind_def;
-
-fun add_inductive_global group flags cnames_syn pnames pre_intros monos thy =
- let
- val name = Sign.full_name thy (fst (fst (hd cnames_syn)));
- val ctxt' = thy
- |> TheoryTarget.init NONE
- |> LocalTheory.set_group group
- |> add_inductive_i flags cnames_syn pnames pre_intros monos |> snd
- |> LocalTheory.exit;
- val info = #2 (the_inductive ctxt' name);
- in (info, ProofContext.theory_of ctxt') end;
-
-
-(* read off arities of inductive predicates from raw induction rule *)
-fun arities_of induct =
- map (fn (_ $ t $ u) =>
- (fst (dest_Const (head_of t)), length (snd (strip_comb u))))
- (HOLogic.dest_conj (HOLogic.dest_Trueprop (concl_of induct)));
-
-(* read off parameters of inductive predicate from raw induction rule *)
-fun params_of induct =
- let
- val (_ $ t $ u :: _) =
- HOLogic.dest_conj (HOLogic.dest_Trueprop (concl_of induct));
- val (_, ts) = strip_comb t;
- val (_, us) = strip_comb u
- in
- List.take (ts, length ts - length us)
- end;
-
-val pname_of_intr =
- concl_of #> HOLogic.dest_Trueprop #> head_of #> dest_Const #> fst;
-
-(* partition introduction rules according to predicate name *)
-fun gen_partition_rules f induct intros =
- fold_rev (fn r => AList.map_entry op = (pname_of_intr (f r)) (cons r)) intros
- (map (rpair [] o fst) (arities_of induct));
-
-val partition_rules = gen_partition_rules I;
-fun partition_rules' induct = gen_partition_rules fst induct;
-
-fun unpartition_rules intros xs =
- fold_map (fn r => AList.map_entry_yield op = (pname_of_intr r)
- (fn x :: xs => (x, xs)) #>> the) intros xs |> fst;
-
-(* infer order of variables in intro rules from order of quantifiers in elim rule *)
-fun infer_intro_vars elim arity intros =
- let
- val thy = theory_of_thm elim;
- val _ :: cases = prems_of elim;
- val used = map (fst o fst) (Term.add_vars (prop_of elim) []);
- fun mtch (t, u) =
- let
- val params = Logic.strip_params t;
- val vars = map (Var o apfst (rpair 0))
- (Name.variant_list used (map fst params) ~~ map snd params);
- val ts = map (curry subst_bounds (rev vars))
- (List.drop (Logic.strip_assums_hyp t, arity));
- val us = Logic.strip_imp_prems u;
- val tab = fold (Pattern.first_order_match thy) (ts ~~ us)
- (Vartab.empty, Vartab.empty);
- in
- map (Envir.subst_vars tab) vars
- end
- in
- map (mtch o apsnd prop_of) (cases ~~ intros)
- end;
-
-
-
-(** package setup **)
-
-(* setup theory *)
-
-val setup =
- ind_cases_setup #>
- Attrib.setup @{binding mono} (Attrib.add_del mono_add mono_del)
- "declaration of monotonicity rule";
-
-
-(* outer syntax *)
-
-local structure P = OuterParse and K = OuterKeyword in
-
-val _ = OuterKeyword.keyword "monos";
-
-fun gen_ind_decl mk_def coind =
- P.fixes -- P.for_fixes --
- Scan.optional SpecParse.where_alt_specs [] --
- Scan.optional (P.$$$ "monos" |-- P.!!! SpecParse.xthms1) []
- >> (fn (((preds, params), specs), monos) =>
- (snd oo gen_add_inductive mk_def true coind preds params specs monos));
-
-val ind_decl = gen_ind_decl add_ind_def;
-
-val _ = OuterSyntax.local_theory' "inductive" "define inductive predicates" K.thy_decl (ind_decl false);
-val _ = OuterSyntax.local_theory' "coinductive" "define coinductive predicates" K.thy_decl (ind_decl true);
-
-val _ =
- OuterSyntax.local_theory "inductive_cases"
- "create simplified instances of elimination rules (improper)" K.thy_script
- (P.and_list1 SpecParse.specs >> (snd oo inductive_cases));
-
-end;
-
-end;
--- a/src/HOL/Tools/inductive_realizer.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/inductive_realizer.ML Fri Jun 19 21:08:07 2009 +0200
@@ -151,7 +151,7 @@
fun is_meta (Const ("all", _) $ Abs (s, _, P)) = is_meta P
| is_meta (Const ("==>", _) $ _ $ Q) = is_meta Q
| is_meta (Const ("Trueprop", _) $ t) = (case head_of t of
- Const (s, _) => can (InductivePackage.the_inductive ctxt) s
+ Const (s, _) => can (Inductive.the_inductive ctxt) s
| _ => true)
| is_meta _ = false;
@@ -277,13 +277,13 @@
val inducts = PureThy.get_thms thy (Long_Name.qualify qualifier "inducts");
val iTs = OldTerm.term_tvars (prop_of (hd intrs));
val ar = length vs + length iTs;
- val params = InductivePackage.params_of raw_induct;
- val arities = InductivePackage.arities_of raw_induct;
+ val params = Inductive.params_of raw_induct;
+ val arities = Inductive.arities_of raw_induct;
val nparms = length params;
val params' = map dest_Var params;
- val rss = InductivePackage.partition_rules raw_induct intrs;
+ val rss = Inductive.partition_rules raw_induct intrs;
val rss' = map (fn (((s, rs), (_, arity)), elim) =>
- (s, (InductivePackage.infer_intro_vars elim arity rs ~~ rs)))
+ (s, (Inductive.infer_intro_vars elim arity rs ~~ rs)))
(rss ~~ arities ~~ elims);
val (prfx, _) = split_last (Long_Name.explode (fst (hd rss)));
val tnames = map (fn s => space_implode "_" (s ^ "T" :: vs)) rsets;
@@ -307,7 +307,7 @@
val ((dummies, dt_info), thy2) =
thy1
- |> add_dummies (DatatypePackage.add_datatype
+ |> add_dummies (Datatype.add_datatype
{ strict = false, flat_names = false, quiet = false } (map (Binding.name_of o #2) dts))
(map (pair false) dts) []
||> Extraction.add_typeof_eqns_i ty_eqs
@@ -348,7 +348,7 @@
(** realizability predicate **)
val (ind_info, thy3') = thy2 |>
- InductivePackage.add_inductive_global (serial_string ())
+ Inductive.add_inductive_global (serial_string ())
{quiet_mode = false, verbose = false, kind = Thm.generatedK, alt_name = Binding.empty,
coind = false, no_elim = false, no_ind = false, skip_mono = false, fork_mono = false}
rlzpreds rlzparams (map (fn (rintr, intr) =>
@@ -483,7 +483,7 @@
fun add_ind_realizers name rsets thy =
let
val (_, {intrs, induct, raw_induct, elims, ...}) =
- InductivePackage.the_inductive (ProofContext.init thy) name;
+ Inductive.the_inductive (ProofContext.init thy) name;
val vss = sort (int_ord o pairself length)
(subsets (map fst (relevant_vars (concl_of (hd intrs)))))
in
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/inductive_set.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,566 @@
+(* Title: HOL/Tools/inductive_set.ML
+ Author: Stefan Berghofer, TU Muenchen
+
+Wrapper for defining inductive sets using package for inductive predicates,
+including infrastructure for converting between predicates and sets.
+*)
+
+signature INDUCTIVE_SET =
+sig
+ val to_set_att: thm list -> attribute
+ val to_pred_att: thm list -> attribute
+ val pred_set_conv_att: attribute
+ val add_inductive_i:
+ Inductive.inductive_flags ->
+ ((binding * typ) * mixfix) list ->
+ (string * typ) list ->
+ (Attrib.binding * term) list -> thm list ->
+ local_theory -> Inductive.inductive_result * local_theory
+ val add_inductive: bool -> bool ->
+ (binding * string option * mixfix) list ->
+ (binding * string option * mixfix) list ->
+ (Attrib.binding * string) list -> (Facts.ref * Attrib.src list) list ->
+ bool -> local_theory -> Inductive.inductive_result * local_theory
+ val codegen_preproc: theory -> thm list -> thm list
+ val setup: theory -> theory
+end;
+
+structure Inductive_Set: INDUCTIVE_SET =
+struct
+
+(**** simplify {(x1, ..., xn). (x1, ..., xn) : S} to S ****)
+
+val collect_mem_simproc =
+ Simplifier.simproc (theory "Set") "Collect_mem" ["Collect t"] (fn thy => fn ss =>
+ fn S as Const ("Collect", Type ("fun", [_, T])) $ t =>
+ let val (u, Ts, ps) = HOLogic.strip_split t
+ in case u of
+ (c as Const ("op :", _)) $ q $ S' =>
+ (case try (HOLogic.dest_tuple' ps) q of
+ NONE => NONE
+ | SOME ts =>
+ if not (loose_bvar (S', 0)) andalso
+ ts = map Bound (length ps downto 0)
+ then
+ let val simp = full_simp_tac (Simplifier.inherit_context ss
+ (HOL_basic_ss addsimps [split_paired_all, split_conv])) 1
+ in
+ SOME (Goal.prove (Simplifier.the_context ss) [] []
+ (Const ("==", T --> T --> propT) $ S $ S')
+ (K (EVERY
+ [rtac eq_reflection 1, rtac @{thm subset_antisym} 1,
+ rtac subsetI 1, dtac CollectD 1, simp,
+ rtac subsetI 1, rtac CollectI 1, simp])))
+ end
+ else NONE)
+ | _ => NONE
+ end
+ | _ => NONE);
+
+(***********************************************************************************)
+(* simplifies (%x y. (x, y) : S & P x y) to (%x y. (x, y) : S Int {(x, y). P x y}) *)
+(* and (%x y. (x, y) : S | P x y) to (%x y. (x, y) : S Un {(x, y). P x y}) *)
+(* used for converting "strong" (co)induction rules *)
+(***********************************************************************************)
+
+val anyt = Free ("t", TFree ("'t", []));
+
+fun strong_ind_simproc tab =
+ Simplifier.simproc_i @{theory HOL} "strong_ind" [anyt] (fn thy => fn ss => fn t =>
+ let
+ fun close p t f =
+ let val vs = Term.add_vars t []
+ in Drule.instantiate' [] (rev (map (SOME o cterm_of thy o Var) vs))
+ (p (fold (Logic.all o Var) vs t) f)
+ end;
+ fun mkop "op &" T x = SOME (Const (@{const_name "Int"}, T --> T --> T), x)
+ | mkop "op |" T x = SOME (Const (@{const_name "Un"}, T --> T --> T), x)
+ | mkop _ _ _ = NONE;
+ fun mk_collect p T t =
+ let val U = HOLogic.dest_setT T
+ in HOLogic.Collect_const U $
+ HOLogic.ap_split' (HOLogic.prod_factors p) U HOLogic.boolT t
+ end;
+ fun decomp (Const (s, _) $ ((m as Const ("op :",
+ Type (_, [_, Type (_, [T, _])]))) $ p $ S) $ u) =
+ mkop s T (m, p, S, mk_collect p T (head_of u))
+ | decomp (Const (s, _) $ u $ ((m as Const ("op :",
+ Type (_, [_, Type (_, [T, _])]))) $ p $ S)) =
+ mkop s T (m, p, mk_collect p T (head_of u), S)
+ | decomp _ = NONE;
+ val simp = full_simp_tac (Simplifier.inherit_context ss
+ (HOL_basic_ss addsimps [mem_Collect_eq, split_conv])) 1;
+ fun mk_rew t = (case strip_abs_vars t of
+ [] => NONE
+ | xs => (case decomp (strip_abs_body t) of
+ NONE => NONE
+ | SOME (bop, (m, p, S, S')) =>
+ SOME (close (Goal.prove (Simplifier.the_context ss) [] [])
+ (Logic.mk_equals (t, list_abs (xs, m $ p $ (bop $ S $ S'))))
+ (K (EVERY
+ [rtac eq_reflection 1, REPEAT (rtac ext 1), rtac iffI 1,
+ EVERY [etac conjE 1, rtac IntI 1, simp, simp,
+ etac IntE 1, rtac conjI 1, simp, simp] ORELSE
+ EVERY [etac disjE 1, rtac UnI1 1, simp, rtac UnI2 1, simp,
+ etac UnE 1, rtac disjI1 1, simp, rtac disjI2 1, simp]])))
+ handle ERROR _ => NONE))
+ in
+ case strip_comb t of
+ (h as Const (name, _), ts) => (case Symtab.lookup tab name of
+ SOME _ =>
+ let val rews = map mk_rew ts
+ in
+ if forall is_none rews then NONE
+ else SOME (fold (fn th1 => fn th2 => combination th2 th1)
+ (map2 (fn SOME r => K r | NONE => reflexive o cterm_of thy)
+ rews ts) (reflexive (cterm_of thy h)))
+ end
+ | NONE => NONE)
+ | _ => NONE
+ end);
+
+(* only eta contract terms occurring as arguments of functions satisfying p *)
+fun eta_contract p =
+ let
+ fun eta b (Abs (a, T, body)) =
+ (case eta b body of
+ body' as (f $ Bound 0) =>
+ if loose_bvar1 (f, 0) orelse not b then Abs (a, T, body')
+ else incr_boundvars ~1 f
+ | body' => Abs (a, T, body'))
+ | eta b (t $ u) = eta b t $ eta (p (head_of t)) u
+ | eta b t = t
+ in eta false end;
+
+fun eta_contract_thm p =
+ Conv.fconv_rule (Conv.then_conv (Thm.beta_conversion true, fn ct =>
+ Thm.transitive (Thm.eta_conversion ct)
+ (Thm.symmetric (Thm.eta_conversion
+ (cterm_of (theory_of_cterm ct) (eta_contract p (term_of ct)))))));
+
+
+(***********************************************************)
+(* rules for converting between predicate and set notation *)
+(* *)
+(* rules for converting predicates to sets have the form *)
+(* P (%x y. (x, y) : s) = (%x y. (x, y) : S s) *)
+(* *)
+(* rules for converting sets to predicates have the form *)
+(* S {(x, y). p x y} = {(x, y). P p x y} *)
+(* *)
+(* where s and p are parameters *)
+(***********************************************************)
+
+structure PredSetConvData = GenericDataFun
+(
+ type T =
+ {(* rules for converting predicates to sets *)
+ to_set_simps: thm list,
+ (* rules for converting sets to predicates *)
+ to_pred_simps: thm list,
+ (* arities of functions of type t set => ... => u set *)
+ set_arities: (typ * (int list list option list * int list list option)) list Symtab.table,
+ (* arities of functions of type (t => ... => bool) => u => ... => bool *)
+ pred_arities: (typ * (int list list option list * int list list option)) list Symtab.table};
+ val empty = {to_set_simps = [], to_pred_simps = [],
+ set_arities = Symtab.empty, pred_arities = Symtab.empty};
+ val extend = I;
+ fun merge _
+ ({to_set_simps = to_set_simps1, to_pred_simps = to_pred_simps1,
+ set_arities = set_arities1, pred_arities = pred_arities1},
+ {to_set_simps = to_set_simps2, to_pred_simps = to_pred_simps2,
+ set_arities = set_arities2, pred_arities = pred_arities2}) : T =
+ {to_set_simps = Thm.merge_thms (to_set_simps1, to_set_simps2),
+ to_pred_simps = Thm.merge_thms (to_pred_simps1, to_pred_simps2),
+ set_arities = Symtab.merge_list op = (set_arities1, set_arities2),
+ pred_arities = Symtab.merge_list op = (pred_arities1, pred_arities2)};
+);
+
+fun name_type_of (Free p) = SOME p
+ | name_type_of (Const p) = SOME p
+ | name_type_of _ = NONE;
+
+fun map_type f (Free (s, T)) = Free (s, f T)
+ | map_type f (Var (ixn, T)) = Var (ixn, f T)
+ | map_type f _ = error "map_type";
+
+fun find_most_specific is_inst f eq xs T =
+ find_first (fn U => is_inst (T, f U)
+ andalso forall (fn U' => eq (f U, f U') orelse not
+ (is_inst (T, f U') andalso is_inst (f U', f U)))
+ xs) xs;
+
+fun lookup_arity thy arities (s, T) = case Symtab.lookup arities s of
+ NONE => NONE
+ | SOME xs => find_most_specific (Sign.typ_instance thy) fst (op =) xs T;
+
+fun lookup_rule thy f rules = find_most_specific
+ (swap #> Pattern.matches thy) (f #> fst) (op aconv) rules;
+
+fun infer_arities thy arities (optf, t) fs = case strip_comb t of
+ (Abs (s, T, u), []) => infer_arities thy arities (NONE, u) fs
+ | (Abs _, _) => infer_arities thy arities (NONE, Envir.beta_norm t) fs
+ | (u, ts) => (case Option.map (lookup_arity thy arities) (name_type_of u) of
+ SOME (SOME (_, (arity, _))) =>
+ (fold (infer_arities thy arities) (arity ~~ List.take (ts, length arity)) fs
+ handle Subscript => error "infer_arities: bad term")
+ | _ => fold (infer_arities thy arities) (map (pair NONE) ts)
+ (case optf of
+ NONE => fs
+ | SOME f => AList.update op = (u, the_default f
+ (Option.map (curry op inter f) (AList.lookup op = fs u))) fs));
+
+
+(**************************************************************)
+(* derive the to_pred equation from the to_set equation *)
+(* *)
+(* 1. instantiate each set parameter with {(x, y). p x y} *)
+(* 2. apply %P. {(x, y). P x y} to both sides of the equation *)
+(* 3. simplify *)
+(**************************************************************)
+
+fun mk_to_pred_inst thy fs =
+ map (fn (x, ps) =>
+ let
+ val U = HOLogic.dest_setT (fastype_of x);
+ val x' = map_type (K (HOLogic.prodT_factors' ps U ---> HOLogic.boolT)) x
+ in
+ (cterm_of thy x,
+ cterm_of thy (HOLogic.Collect_const U $
+ HOLogic.ap_split' ps U HOLogic.boolT x'))
+ end) fs;
+
+fun mk_to_pred_eq p fs optfs' T thm =
+ let
+ val thy = theory_of_thm thm;
+ val insts = mk_to_pred_inst thy fs;
+ val thm' = Thm.instantiate ([], insts) thm;
+ val thm'' = (case optfs' of
+ NONE => thm' RS sym
+ | SOME fs' =>
+ let
+ val (_, U) = split_last (binder_types T);
+ val Ts = HOLogic.prodT_factors' fs' U;
+ (* FIXME: should cterm_instantiate increment indexes? *)
+ val arg_cong' = Thm.incr_indexes (Thm.maxidx_of thm + 1) arg_cong;
+ val (arg_cong_f, _) = arg_cong' |> cprop_of |> Drule.strip_imp_concl |>
+ Thm.dest_comb |> snd |> Drule.strip_comb |> snd |> hd |> Thm.dest_comb
+ in
+ thm' RS (Drule.cterm_instantiate [(arg_cong_f,
+ cterm_of thy (Abs ("P", Ts ---> HOLogic.boolT,
+ HOLogic.Collect_const U $ HOLogic.ap_split' fs' U
+ HOLogic.boolT (Bound 0))))] arg_cong' RS sym)
+ end)
+ in
+ Simplifier.simplify (HOL_basic_ss addsimps [mem_Collect_eq, split_conv]
+ addsimprocs [collect_mem_simproc]) thm'' |>
+ zero_var_indexes |> eta_contract_thm (equal p)
+ end;
+
+
+(**** declare rules for converting predicates to sets ****)
+
+fun add ctxt thm (tab as {to_set_simps, to_pred_simps, set_arities, pred_arities}) =
+ case prop_of thm of
+ Const ("Trueprop", _) $ (Const ("op =", Type (_, [T, _])) $ lhs $ rhs) =>
+ (case body_type T of
+ Type ("bool", []) =>
+ let
+ val thy = Context.theory_of ctxt;
+ fun factors_of t fs = case strip_abs_body t of
+ Const ("op :", _) $ u $ S =>
+ if is_Free S orelse is_Var S then
+ let val ps = HOLogic.prod_factors u
+ in (SOME ps, (S, ps) :: fs) end
+ else (NONE, fs)
+ | _ => (NONE, fs);
+ val (h, ts) = strip_comb lhs
+ val (pfs, fs) = fold_map factors_of ts [];
+ val ((h', ts'), fs') = (case rhs of
+ Abs _ => (case strip_abs_body rhs of
+ Const ("op :", _) $ u $ S =>
+ (strip_comb S, SOME (HOLogic.prod_factors u))
+ | _ => error "member symbol on right-hand side expected")
+ | _ => (strip_comb rhs, NONE))
+ in
+ case (name_type_of h, name_type_of h') of
+ (SOME (s, T), SOME (s', T')) =>
+ if exists (fn (U, _) =>
+ Sign.typ_instance thy (T', U) andalso
+ Sign.typ_instance thy (U, T'))
+ (Symtab.lookup_list set_arities s')
+ then
+ (warning ("Ignoring conversion rule for operator " ^ s'); tab)
+ else
+ {to_set_simps = thm :: to_set_simps,
+ to_pred_simps =
+ mk_to_pred_eq h fs fs' T' thm :: to_pred_simps,
+ set_arities = Symtab.insert_list op = (s',
+ (T', (map (AList.lookup op = fs) ts', fs'))) set_arities,
+ pred_arities = Symtab.insert_list op = (s,
+ (T, (pfs, fs'))) pred_arities}
+ | _ => error "set / predicate constant expected"
+ end
+ | _ => error "equation between predicates expected")
+ | _ => error "equation expected";
+
+val pred_set_conv_att = Thm.declaration_attribute
+ (fn thm => fn ctxt => PredSetConvData.map (add ctxt thm) ctxt);
+
+
+(**** convert theorem in set notation to predicate notation ****)
+
+fun is_pred tab t =
+ case Option.map (Symtab.lookup tab o fst) (name_type_of t) of
+ SOME (SOME _) => true | _ => false;
+
+fun to_pred_simproc rules =
+ let val rules' = map mk_meta_eq rules
+ in
+ Simplifier.simproc_i @{theory HOL} "to_pred" [anyt]
+ (fn thy => K (lookup_rule thy (prop_of #> Logic.dest_equals) rules'))
+ end;
+
+fun to_pred_proc thy rules t = case lookup_rule thy I rules t of
+ NONE => NONE
+ | SOME (lhs, rhs) =>
+ SOME (Envir.subst_vars
+ (Pattern.match thy (lhs, t) (Vartab.empty, Vartab.empty)) rhs);
+
+fun to_pred thms ctxt thm =
+ let
+ val thy = Context.theory_of ctxt;
+ val {to_pred_simps, set_arities, pred_arities, ...} =
+ fold (add ctxt) thms (PredSetConvData.get ctxt);
+ val fs = filter (is_Var o fst)
+ (infer_arities thy set_arities (NONE, prop_of thm) []);
+ (* instantiate each set parameter with {(x, y). p x y} *)
+ val insts = mk_to_pred_inst thy fs
+ in
+ thm |>
+ Thm.instantiate ([], insts) |>
+ Simplifier.full_simplify (HOL_basic_ss addsimprocs
+ [to_pred_simproc (mem_Collect_eq :: split_conv :: to_pred_simps)]) |>
+ eta_contract_thm (is_pred pred_arities) |>
+ RuleCases.save thm
+ end;
+
+val to_pred_att = Thm.rule_attribute o to_pred;
+
+
+(**** convert theorem in predicate notation to set notation ****)
+
+fun to_set thms ctxt thm =
+ let
+ val thy = Context.theory_of ctxt;
+ val {to_set_simps, pred_arities, ...} =
+ fold (add ctxt) thms (PredSetConvData.get ctxt);
+ val fs = filter (is_Var o fst)
+ (infer_arities thy pred_arities (NONE, prop_of thm) []);
+ (* instantiate each predicate parameter with %x y. (x, y) : s *)
+ val insts = map (fn (x, ps) =>
+ let
+ val Ts = binder_types (fastype_of x);
+ val T = HOLogic.mk_tupleT ps Ts;
+ val x' = map_type (K (HOLogic.mk_setT T)) x
+ in
+ (cterm_of thy x,
+ cterm_of thy (list_abs (map (pair "x") Ts, HOLogic.mk_mem
+ (HOLogic.mk_tuple' ps T (map Bound (length ps downto 0)), x'))))
+ end) fs
+ in
+ thm |>
+ Thm.instantiate ([], insts) |>
+ Simplifier.full_simplify (HOL_basic_ss addsimps to_set_simps
+ addsimprocs [strong_ind_simproc pred_arities, collect_mem_simproc]) |>
+ RuleCases.save thm
+ end;
+
+val to_set_att = Thm.rule_attribute o to_set;
+
+
+(**** preprocessor for code generator ****)
+
+fun codegen_preproc thy =
+ let
+ val {to_pred_simps, set_arities, pred_arities, ...} =
+ PredSetConvData.get (Context.Theory thy);
+ fun preproc thm =
+ if exists_Const (fn (s, _) => case Symtab.lookup set_arities s of
+ NONE => false
+ | SOME arities => exists (fn (_, (xs, _)) =>
+ forall is_none xs) arities) (prop_of thm)
+ then
+ thm |>
+ Simplifier.full_simplify (HOL_basic_ss addsimprocs
+ [to_pred_simproc (mem_Collect_eq :: split_conv :: to_pred_simps)]) |>
+ eta_contract_thm (is_pred pred_arities)
+ else thm
+ in map preproc end;
+
+fun code_ind_att optmod = to_pred_att [] #> InductiveCodegen.add optmod NONE;
+
+
+(**** definition of inductive sets ****)
+
+fun add_ind_set_def
+ {quiet_mode, verbose, kind, alt_name, coind, no_elim, no_ind, skip_mono, fork_mono}
+ cs intros monos params cnames_syn ctxt =
+ let
+ val thy = ProofContext.theory_of ctxt;
+ val {set_arities, pred_arities, to_pred_simps, ...} =
+ PredSetConvData.get (Context.Proof ctxt);
+ fun infer (Abs (_, _, t)) = infer t
+ | infer (Const ("op :", _) $ t $ u) =
+ infer_arities thy set_arities (SOME (HOLogic.prod_factors t), u)
+ | infer (t $ u) = infer t #> infer u
+ | infer _ = I;
+ val new_arities = filter_out
+ (fn (x as Free (_, T), _) => x mem params andalso length (binder_types T) > 1
+ | _ => false) (fold (snd #> infer) intros []);
+ val params' = map (fn x => (case AList.lookup op = new_arities x of
+ SOME fs =>
+ let
+ val T = HOLogic.dest_setT (fastype_of x);
+ val Ts = HOLogic.prodT_factors' fs T;
+ val x' = map_type (K (Ts ---> HOLogic.boolT)) x
+ in
+ (x, (x',
+ (HOLogic.Collect_const T $
+ HOLogic.ap_split' fs T HOLogic.boolT x',
+ list_abs (map (pair "x") Ts, HOLogic.mk_mem
+ (HOLogic.mk_tuple' fs T (map Bound (length fs downto 0)),
+ x)))))
+ end
+ | NONE => (x, (x, (x, x))))) params;
+ val (params1, (params2, params3)) =
+ params' |> map snd |> split_list ||> split_list;
+ val paramTs = map fastype_of params;
+
+ (* equations for converting sets to predicates *)
+ val ((cs', cs_info), eqns) = cs |> map (fn c as Free (s, T) =>
+ let
+ val fs = the_default [] (AList.lookup op = new_arities c);
+ val (Us, U) = split_last (binder_types T);
+ val _ = Us = paramTs orelse error (Pretty.string_of (Pretty.chunks
+ [Pretty.str "Argument types",
+ Pretty.block (Pretty.commas (map (Syntax.pretty_typ ctxt) Us)),
+ Pretty.str ("of " ^ s ^ " do not agree with types"),
+ Pretty.block (Pretty.commas (map (Syntax.pretty_typ ctxt) paramTs)),
+ Pretty.str "of declared parameters"]));
+ val Ts = HOLogic.prodT_factors' fs U;
+ val c' = Free (s ^ "p",
+ map fastype_of params1 @ Ts ---> HOLogic.boolT)
+ in
+ ((c', (fs, U, Ts)),
+ (list_comb (c, params2),
+ HOLogic.Collect_const U $ HOLogic.ap_split' fs U HOLogic.boolT
+ (list_comb (c', params1))))
+ end) |> split_list |>> split_list;
+ val eqns' = eqns @
+ map (prop_of #> HOLogic.dest_Trueprop #> HOLogic.dest_eq)
+ (mem_Collect_eq :: split_conv :: to_pred_simps);
+
+ (* predicate version of the introduction rules *)
+ val intros' =
+ map (fn (name_atts, t) => (name_atts,
+ t |>
+ map_aterms (fn u =>
+ (case AList.lookup op = params' u of
+ SOME (_, (u', _)) => u'
+ | NONE => u)) |>
+ Pattern.rewrite_term thy [] [to_pred_proc thy eqns'] |>
+ eta_contract (member op = cs' orf is_pred pred_arities))) intros;
+ val cnames_syn' = map (fn (b, _) => (Binding.suffix_name "p" b, NoSyn)) cnames_syn;
+ val monos' = map (to_pred [] (Context.Proof ctxt)) monos;
+ val ({preds, intrs, elims, raw_induct, ...}, ctxt1) =
+ Inductive.add_ind_def
+ {quiet_mode = quiet_mode, verbose = verbose, kind = kind, alt_name = Binding.empty,
+ coind = coind, no_elim = no_elim, no_ind = no_ind,
+ skip_mono = skip_mono, fork_mono = fork_mono}
+ cs' intros' monos' params1 cnames_syn' ctxt;
+
+ (* define inductive sets using previously defined predicates *)
+ val (defs, ctxt2) = fold_map (LocalTheory.define Thm.internalK)
+ (map (fn ((c_syn, (fs, U, _)), p) => (c_syn, (Attrib.empty_binding,
+ fold_rev lambda params (HOLogic.Collect_const U $
+ HOLogic.ap_split' fs U HOLogic.boolT (list_comb (p, params3))))))
+ (cnames_syn ~~ cs_info ~~ preds)) ctxt1;
+
+ (* prove theorems for converting predicate to set notation *)
+ val ctxt3 = fold
+ (fn (((p, c as Free (s, _)), (fs, U, Ts)), (_, (_, def))) => fn ctxt =>
+ let val conv_thm =
+ Goal.prove ctxt (map (fst o dest_Free) params) []
+ (HOLogic.mk_Trueprop (HOLogic.mk_eq
+ (list_comb (p, params3),
+ list_abs (map (pair "x") Ts, HOLogic.mk_mem
+ (HOLogic.mk_tuple' fs U (map Bound (length fs downto 0)),
+ list_comb (c, params))))))
+ (K (REPEAT (rtac ext 1) THEN simp_tac (HOL_basic_ss addsimps
+ [def, mem_Collect_eq, split_conv]) 1))
+ in
+ ctxt |> LocalTheory.note kind ((Binding.name (s ^ "p_" ^ s ^ "_eq"),
+ [Attrib.internal (K pred_set_conv_att)]),
+ [conv_thm]) |> snd
+ end) (preds ~~ cs ~~ cs_info ~~ defs) ctxt2;
+
+ (* convert theorems to set notation *)
+ val rec_name =
+ if Binding.is_empty alt_name then
+ Binding.name (space_implode "_" (map (Binding.name_of o fst) cnames_syn))
+ else alt_name;
+ val cnames = map (LocalTheory.full_name ctxt3 o #1) cnames_syn; (* FIXME *)
+ val (intr_names, intr_atts) = split_list (map fst intros);
+ val raw_induct' = to_set [] (Context.Proof ctxt3) raw_induct;
+ val (intrs', elims', induct, ctxt4) =
+ Inductive.declare_rules kind rec_name coind no_ind cnames
+ (map (to_set [] (Context.Proof ctxt3)) intrs) intr_names intr_atts
+ (map (fn th => (to_set [] (Context.Proof ctxt3) th,
+ map fst (fst (RuleCases.get th)))) elims)
+ raw_induct' ctxt3
+ in
+ ({intrs = intrs', elims = elims', induct = induct,
+ raw_induct = raw_induct', preds = map fst defs},
+ ctxt4)
+ end;
+
+val add_inductive_i = Inductive.gen_add_inductive_i add_ind_set_def;
+val add_inductive = Inductive.gen_add_inductive add_ind_set_def;
+
+val mono_add_att = to_pred_att [] #> Inductive.mono_add;
+val mono_del_att = to_pred_att [] #> Inductive.mono_del;
+
+
+(** package setup **)
+
+(* setup theory *)
+
+val setup =
+ Attrib.setup @{binding pred_set_conv} (Scan.succeed pred_set_conv_att)
+ "declare rules for converting between predicate and set notation" #>
+ Attrib.setup @{binding to_set} (Attrib.thms >> to_set_att) "convert rule to set notation" #>
+ Attrib.setup @{binding to_pred} (Attrib.thms >> to_pred_att) "convert rule to predicate notation" #>
+ Code.add_attribute ("ind_set",
+ Scan.option (Args.$$$ "target" |-- Args.colon |-- Args.name) >> code_ind_att) #>
+ Codegen.add_preprocessor codegen_preproc #>
+ Attrib.setup @{binding mono_set} (Attrib.add_del mono_add_att mono_del_att)
+ "declaration of monotonicity rule for set operators" #>
+ Context.theory_map (Simplifier.map_ss (fn ss => ss addsimprocs [collect_mem_simproc]));
+
+
+(* outer syntax *)
+
+local structure P = OuterParse and K = OuterKeyword in
+
+val ind_set_decl = Inductive.gen_ind_decl add_ind_set_def;
+
+val _ =
+ OuterSyntax.local_theory' "inductive_set" "define inductive sets" K.thy_decl (ind_set_decl false);
+
+val _ =
+ OuterSyntax.local_theory' "coinductive_set" "define coinductive sets" K.thy_decl (ind_set_decl true);
+
+end;
+
+end;
--- a/src/HOL/Tools/inductive_set_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,566 +0,0 @@
-(* Title: HOL/Tools/inductive_set_package.ML
- Author: Stefan Berghofer, TU Muenchen
-
-Wrapper for defining inductive sets using package for inductive predicates,
-including infrastructure for converting between predicates and sets.
-*)
-
-signature INDUCTIVE_SET_PACKAGE =
-sig
- val to_set_att: thm list -> attribute
- val to_pred_att: thm list -> attribute
- val pred_set_conv_att: attribute
- val add_inductive_i:
- InductivePackage.inductive_flags ->
- ((binding * typ) * mixfix) list ->
- (string * typ) list ->
- (Attrib.binding * term) list -> thm list ->
- local_theory -> InductivePackage.inductive_result * local_theory
- val add_inductive: bool -> bool ->
- (binding * string option * mixfix) list ->
- (binding * string option * mixfix) list ->
- (Attrib.binding * string) list -> (Facts.ref * Attrib.src list) list ->
- bool -> local_theory -> InductivePackage.inductive_result * local_theory
- val codegen_preproc: theory -> thm list -> thm list
- val setup: theory -> theory
-end;
-
-structure InductiveSetPackage: INDUCTIVE_SET_PACKAGE =
-struct
-
-(**** simplify {(x1, ..., xn). (x1, ..., xn) : S} to S ****)
-
-val collect_mem_simproc =
- Simplifier.simproc (theory "Set") "Collect_mem" ["Collect t"] (fn thy => fn ss =>
- fn S as Const ("Collect", Type ("fun", [_, T])) $ t =>
- let val (u, Ts, ps) = HOLogic.strip_split t
- in case u of
- (c as Const ("op :", _)) $ q $ S' =>
- (case try (HOLogic.dest_tuple' ps) q of
- NONE => NONE
- | SOME ts =>
- if not (loose_bvar (S', 0)) andalso
- ts = map Bound (length ps downto 0)
- then
- let val simp = full_simp_tac (Simplifier.inherit_context ss
- (HOL_basic_ss addsimps [split_paired_all, split_conv])) 1
- in
- SOME (Goal.prove (Simplifier.the_context ss) [] []
- (Const ("==", T --> T --> propT) $ S $ S')
- (K (EVERY
- [rtac eq_reflection 1, rtac @{thm subset_antisym} 1,
- rtac subsetI 1, dtac CollectD 1, simp,
- rtac subsetI 1, rtac CollectI 1, simp])))
- end
- else NONE)
- | _ => NONE
- end
- | _ => NONE);
-
-(***********************************************************************************)
-(* simplifies (%x y. (x, y) : S & P x y) to (%x y. (x, y) : S Int {(x, y). P x y}) *)
-(* and (%x y. (x, y) : S | P x y) to (%x y. (x, y) : S Un {(x, y). P x y}) *)
-(* used for converting "strong" (co)induction rules *)
-(***********************************************************************************)
-
-val anyt = Free ("t", TFree ("'t", []));
-
-fun strong_ind_simproc tab =
- Simplifier.simproc_i @{theory HOL} "strong_ind" [anyt] (fn thy => fn ss => fn t =>
- let
- fun close p t f =
- let val vs = Term.add_vars t []
- in Drule.instantiate' [] (rev (map (SOME o cterm_of thy o Var) vs))
- (p (fold (Logic.all o Var) vs t) f)
- end;
- fun mkop "op &" T x = SOME (Const (@{const_name "Int"}, T --> T --> T), x)
- | mkop "op |" T x = SOME (Const (@{const_name "Un"}, T --> T --> T), x)
- | mkop _ _ _ = NONE;
- fun mk_collect p T t =
- let val U = HOLogic.dest_setT T
- in HOLogic.Collect_const U $
- HOLogic.ap_split' (HOLogic.prod_factors p) U HOLogic.boolT t
- end;
- fun decomp (Const (s, _) $ ((m as Const ("op :",
- Type (_, [_, Type (_, [T, _])]))) $ p $ S) $ u) =
- mkop s T (m, p, S, mk_collect p T (head_of u))
- | decomp (Const (s, _) $ u $ ((m as Const ("op :",
- Type (_, [_, Type (_, [T, _])]))) $ p $ S)) =
- mkop s T (m, p, mk_collect p T (head_of u), S)
- | decomp _ = NONE;
- val simp = full_simp_tac (Simplifier.inherit_context ss
- (HOL_basic_ss addsimps [mem_Collect_eq, split_conv])) 1;
- fun mk_rew t = (case strip_abs_vars t of
- [] => NONE
- | xs => (case decomp (strip_abs_body t) of
- NONE => NONE
- | SOME (bop, (m, p, S, S')) =>
- SOME (close (Goal.prove (Simplifier.the_context ss) [] [])
- (Logic.mk_equals (t, list_abs (xs, m $ p $ (bop $ S $ S'))))
- (K (EVERY
- [rtac eq_reflection 1, REPEAT (rtac ext 1), rtac iffI 1,
- EVERY [etac conjE 1, rtac IntI 1, simp, simp,
- etac IntE 1, rtac conjI 1, simp, simp] ORELSE
- EVERY [etac disjE 1, rtac UnI1 1, simp, rtac UnI2 1, simp,
- etac UnE 1, rtac disjI1 1, simp, rtac disjI2 1, simp]])))
- handle ERROR _ => NONE))
- in
- case strip_comb t of
- (h as Const (name, _), ts) => (case Symtab.lookup tab name of
- SOME _ =>
- let val rews = map mk_rew ts
- in
- if forall is_none rews then NONE
- else SOME (fold (fn th1 => fn th2 => combination th2 th1)
- (map2 (fn SOME r => K r | NONE => reflexive o cterm_of thy)
- rews ts) (reflexive (cterm_of thy h)))
- end
- | NONE => NONE)
- | _ => NONE
- end);
-
-(* only eta contract terms occurring as arguments of functions satisfying p *)
-fun eta_contract p =
- let
- fun eta b (Abs (a, T, body)) =
- (case eta b body of
- body' as (f $ Bound 0) =>
- if loose_bvar1 (f, 0) orelse not b then Abs (a, T, body')
- else incr_boundvars ~1 f
- | body' => Abs (a, T, body'))
- | eta b (t $ u) = eta b t $ eta (p (head_of t)) u
- | eta b t = t
- in eta false end;
-
-fun eta_contract_thm p =
- Conv.fconv_rule (Conv.then_conv (Thm.beta_conversion true, fn ct =>
- Thm.transitive (Thm.eta_conversion ct)
- (Thm.symmetric (Thm.eta_conversion
- (cterm_of (theory_of_cterm ct) (eta_contract p (term_of ct)))))));
-
-
-(***********************************************************)
-(* rules for converting between predicate and set notation *)
-(* *)
-(* rules for converting predicates to sets have the form *)
-(* P (%x y. (x, y) : s) = (%x y. (x, y) : S s) *)
-(* *)
-(* rules for converting sets to predicates have the form *)
-(* S {(x, y). p x y} = {(x, y). P p x y} *)
-(* *)
-(* where s and p are parameters *)
-(***********************************************************)
-
-structure PredSetConvData = GenericDataFun
-(
- type T =
- {(* rules for converting predicates to sets *)
- to_set_simps: thm list,
- (* rules for converting sets to predicates *)
- to_pred_simps: thm list,
- (* arities of functions of type t set => ... => u set *)
- set_arities: (typ * (int list list option list * int list list option)) list Symtab.table,
- (* arities of functions of type (t => ... => bool) => u => ... => bool *)
- pred_arities: (typ * (int list list option list * int list list option)) list Symtab.table};
- val empty = {to_set_simps = [], to_pred_simps = [],
- set_arities = Symtab.empty, pred_arities = Symtab.empty};
- val extend = I;
- fun merge _
- ({to_set_simps = to_set_simps1, to_pred_simps = to_pred_simps1,
- set_arities = set_arities1, pred_arities = pred_arities1},
- {to_set_simps = to_set_simps2, to_pred_simps = to_pred_simps2,
- set_arities = set_arities2, pred_arities = pred_arities2}) : T =
- {to_set_simps = Thm.merge_thms (to_set_simps1, to_set_simps2),
- to_pred_simps = Thm.merge_thms (to_pred_simps1, to_pred_simps2),
- set_arities = Symtab.merge_list op = (set_arities1, set_arities2),
- pred_arities = Symtab.merge_list op = (pred_arities1, pred_arities2)};
-);
-
-fun name_type_of (Free p) = SOME p
- | name_type_of (Const p) = SOME p
- | name_type_of _ = NONE;
-
-fun map_type f (Free (s, T)) = Free (s, f T)
- | map_type f (Var (ixn, T)) = Var (ixn, f T)
- | map_type f _ = error "map_type";
-
-fun find_most_specific is_inst f eq xs T =
- find_first (fn U => is_inst (T, f U)
- andalso forall (fn U' => eq (f U, f U') orelse not
- (is_inst (T, f U') andalso is_inst (f U', f U)))
- xs) xs;
-
-fun lookup_arity thy arities (s, T) = case Symtab.lookup arities s of
- NONE => NONE
- | SOME xs => find_most_specific (Sign.typ_instance thy) fst (op =) xs T;
-
-fun lookup_rule thy f rules = find_most_specific
- (swap #> Pattern.matches thy) (f #> fst) (op aconv) rules;
-
-fun infer_arities thy arities (optf, t) fs = case strip_comb t of
- (Abs (s, T, u), []) => infer_arities thy arities (NONE, u) fs
- | (Abs _, _) => infer_arities thy arities (NONE, Envir.beta_norm t) fs
- | (u, ts) => (case Option.map (lookup_arity thy arities) (name_type_of u) of
- SOME (SOME (_, (arity, _))) =>
- (fold (infer_arities thy arities) (arity ~~ List.take (ts, length arity)) fs
- handle Subscript => error "infer_arities: bad term")
- | _ => fold (infer_arities thy arities) (map (pair NONE) ts)
- (case optf of
- NONE => fs
- | SOME f => AList.update op = (u, the_default f
- (Option.map (curry op inter f) (AList.lookup op = fs u))) fs));
-
-
-(**************************************************************)
-(* derive the to_pred equation from the to_set equation *)
-(* *)
-(* 1. instantiate each set parameter with {(x, y). p x y} *)
-(* 2. apply %P. {(x, y). P x y} to both sides of the equation *)
-(* 3. simplify *)
-(**************************************************************)
-
-fun mk_to_pred_inst thy fs =
- map (fn (x, ps) =>
- let
- val U = HOLogic.dest_setT (fastype_of x);
- val x' = map_type (K (HOLogic.prodT_factors' ps U ---> HOLogic.boolT)) x
- in
- (cterm_of thy x,
- cterm_of thy (HOLogic.Collect_const U $
- HOLogic.ap_split' ps U HOLogic.boolT x'))
- end) fs;
-
-fun mk_to_pred_eq p fs optfs' T thm =
- let
- val thy = theory_of_thm thm;
- val insts = mk_to_pred_inst thy fs;
- val thm' = Thm.instantiate ([], insts) thm;
- val thm'' = (case optfs' of
- NONE => thm' RS sym
- | SOME fs' =>
- let
- val (_, U) = split_last (binder_types T);
- val Ts = HOLogic.prodT_factors' fs' U;
- (* FIXME: should cterm_instantiate increment indexes? *)
- val arg_cong' = Thm.incr_indexes (Thm.maxidx_of thm + 1) arg_cong;
- val (arg_cong_f, _) = arg_cong' |> cprop_of |> Drule.strip_imp_concl |>
- Thm.dest_comb |> snd |> Drule.strip_comb |> snd |> hd |> Thm.dest_comb
- in
- thm' RS (Drule.cterm_instantiate [(arg_cong_f,
- cterm_of thy (Abs ("P", Ts ---> HOLogic.boolT,
- HOLogic.Collect_const U $ HOLogic.ap_split' fs' U
- HOLogic.boolT (Bound 0))))] arg_cong' RS sym)
- end)
- in
- Simplifier.simplify (HOL_basic_ss addsimps [mem_Collect_eq, split_conv]
- addsimprocs [collect_mem_simproc]) thm'' |>
- zero_var_indexes |> eta_contract_thm (equal p)
- end;
-
-
-(**** declare rules for converting predicates to sets ****)
-
-fun add ctxt thm (tab as {to_set_simps, to_pred_simps, set_arities, pred_arities}) =
- case prop_of thm of
- Const ("Trueprop", _) $ (Const ("op =", Type (_, [T, _])) $ lhs $ rhs) =>
- (case body_type T of
- Type ("bool", []) =>
- let
- val thy = Context.theory_of ctxt;
- fun factors_of t fs = case strip_abs_body t of
- Const ("op :", _) $ u $ S =>
- if is_Free S orelse is_Var S then
- let val ps = HOLogic.prod_factors u
- in (SOME ps, (S, ps) :: fs) end
- else (NONE, fs)
- | _ => (NONE, fs);
- val (h, ts) = strip_comb lhs
- val (pfs, fs) = fold_map factors_of ts [];
- val ((h', ts'), fs') = (case rhs of
- Abs _ => (case strip_abs_body rhs of
- Const ("op :", _) $ u $ S =>
- (strip_comb S, SOME (HOLogic.prod_factors u))
- | _ => error "member symbol on right-hand side expected")
- | _ => (strip_comb rhs, NONE))
- in
- case (name_type_of h, name_type_of h') of
- (SOME (s, T), SOME (s', T')) =>
- if exists (fn (U, _) =>
- Sign.typ_instance thy (T', U) andalso
- Sign.typ_instance thy (U, T'))
- (Symtab.lookup_list set_arities s')
- then
- (warning ("Ignoring conversion rule for operator " ^ s'); tab)
- else
- {to_set_simps = thm :: to_set_simps,
- to_pred_simps =
- mk_to_pred_eq h fs fs' T' thm :: to_pred_simps,
- set_arities = Symtab.insert_list op = (s',
- (T', (map (AList.lookup op = fs) ts', fs'))) set_arities,
- pred_arities = Symtab.insert_list op = (s,
- (T, (pfs, fs'))) pred_arities}
- | _ => error "set / predicate constant expected"
- end
- | _ => error "equation between predicates expected")
- | _ => error "equation expected";
-
-val pred_set_conv_att = Thm.declaration_attribute
- (fn thm => fn ctxt => PredSetConvData.map (add ctxt thm) ctxt);
-
-
-(**** convert theorem in set notation to predicate notation ****)
-
-fun is_pred tab t =
- case Option.map (Symtab.lookup tab o fst) (name_type_of t) of
- SOME (SOME _) => true | _ => false;
-
-fun to_pred_simproc rules =
- let val rules' = map mk_meta_eq rules
- in
- Simplifier.simproc_i @{theory HOL} "to_pred" [anyt]
- (fn thy => K (lookup_rule thy (prop_of #> Logic.dest_equals) rules'))
- end;
-
-fun to_pred_proc thy rules t = case lookup_rule thy I rules t of
- NONE => NONE
- | SOME (lhs, rhs) =>
- SOME (Envir.subst_vars
- (Pattern.match thy (lhs, t) (Vartab.empty, Vartab.empty)) rhs);
-
-fun to_pred thms ctxt thm =
- let
- val thy = Context.theory_of ctxt;
- val {to_pred_simps, set_arities, pred_arities, ...} =
- fold (add ctxt) thms (PredSetConvData.get ctxt);
- val fs = filter (is_Var o fst)
- (infer_arities thy set_arities (NONE, prop_of thm) []);
- (* instantiate each set parameter with {(x, y). p x y} *)
- val insts = mk_to_pred_inst thy fs
- in
- thm |>
- Thm.instantiate ([], insts) |>
- Simplifier.full_simplify (HOL_basic_ss addsimprocs
- [to_pred_simproc (mem_Collect_eq :: split_conv :: to_pred_simps)]) |>
- eta_contract_thm (is_pred pred_arities) |>
- RuleCases.save thm
- end;
-
-val to_pred_att = Thm.rule_attribute o to_pred;
-
-
-(**** convert theorem in predicate notation to set notation ****)
-
-fun to_set thms ctxt thm =
- let
- val thy = Context.theory_of ctxt;
- val {to_set_simps, pred_arities, ...} =
- fold (add ctxt) thms (PredSetConvData.get ctxt);
- val fs = filter (is_Var o fst)
- (infer_arities thy pred_arities (NONE, prop_of thm) []);
- (* instantiate each predicate parameter with %x y. (x, y) : s *)
- val insts = map (fn (x, ps) =>
- let
- val Ts = binder_types (fastype_of x);
- val T = HOLogic.mk_tupleT ps Ts;
- val x' = map_type (K (HOLogic.mk_setT T)) x
- in
- (cterm_of thy x,
- cterm_of thy (list_abs (map (pair "x") Ts, HOLogic.mk_mem
- (HOLogic.mk_tuple' ps T (map Bound (length ps downto 0)), x'))))
- end) fs
- in
- thm |>
- Thm.instantiate ([], insts) |>
- Simplifier.full_simplify (HOL_basic_ss addsimps to_set_simps
- addsimprocs [strong_ind_simproc pred_arities, collect_mem_simproc]) |>
- RuleCases.save thm
- end;
-
-val to_set_att = Thm.rule_attribute o to_set;
-
-
-(**** preprocessor for code generator ****)
-
-fun codegen_preproc thy =
- let
- val {to_pred_simps, set_arities, pred_arities, ...} =
- PredSetConvData.get (Context.Theory thy);
- fun preproc thm =
- if exists_Const (fn (s, _) => case Symtab.lookup set_arities s of
- NONE => false
- | SOME arities => exists (fn (_, (xs, _)) =>
- forall is_none xs) arities) (prop_of thm)
- then
- thm |>
- Simplifier.full_simplify (HOL_basic_ss addsimprocs
- [to_pred_simproc (mem_Collect_eq :: split_conv :: to_pred_simps)]) |>
- eta_contract_thm (is_pred pred_arities)
- else thm
- in map preproc end;
-
-fun code_ind_att optmod = to_pred_att [] #> InductiveCodegen.add optmod NONE;
-
-
-(**** definition of inductive sets ****)
-
-fun add_ind_set_def
- {quiet_mode, verbose, kind, alt_name, coind, no_elim, no_ind, skip_mono, fork_mono}
- cs intros monos params cnames_syn ctxt =
- let
- val thy = ProofContext.theory_of ctxt;
- val {set_arities, pred_arities, to_pred_simps, ...} =
- PredSetConvData.get (Context.Proof ctxt);
- fun infer (Abs (_, _, t)) = infer t
- | infer (Const ("op :", _) $ t $ u) =
- infer_arities thy set_arities (SOME (HOLogic.prod_factors t), u)
- | infer (t $ u) = infer t #> infer u
- | infer _ = I;
- val new_arities = filter_out
- (fn (x as Free (_, T), _) => x mem params andalso length (binder_types T) > 1
- | _ => false) (fold (snd #> infer) intros []);
- val params' = map (fn x => (case AList.lookup op = new_arities x of
- SOME fs =>
- let
- val T = HOLogic.dest_setT (fastype_of x);
- val Ts = HOLogic.prodT_factors' fs T;
- val x' = map_type (K (Ts ---> HOLogic.boolT)) x
- in
- (x, (x',
- (HOLogic.Collect_const T $
- HOLogic.ap_split' fs T HOLogic.boolT x',
- list_abs (map (pair "x") Ts, HOLogic.mk_mem
- (HOLogic.mk_tuple' fs T (map Bound (length fs downto 0)),
- x)))))
- end
- | NONE => (x, (x, (x, x))))) params;
- val (params1, (params2, params3)) =
- params' |> map snd |> split_list ||> split_list;
- val paramTs = map fastype_of params;
-
- (* equations for converting sets to predicates *)
- val ((cs', cs_info), eqns) = cs |> map (fn c as Free (s, T) =>
- let
- val fs = the_default [] (AList.lookup op = new_arities c);
- val (Us, U) = split_last (binder_types T);
- val _ = Us = paramTs orelse error (Pretty.string_of (Pretty.chunks
- [Pretty.str "Argument types",
- Pretty.block (Pretty.commas (map (Syntax.pretty_typ ctxt) Us)),
- Pretty.str ("of " ^ s ^ " do not agree with types"),
- Pretty.block (Pretty.commas (map (Syntax.pretty_typ ctxt) paramTs)),
- Pretty.str "of declared parameters"]));
- val Ts = HOLogic.prodT_factors' fs U;
- val c' = Free (s ^ "p",
- map fastype_of params1 @ Ts ---> HOLogic.boolT)
- in
- ((c', (fs, U, Ts)),
- (list_comb (c, params2),
- HOLogic.Collect_const U $ HOLogic.ap_split' fs U HOLogic.boolT
- (list_comb (c', params1))))
- end) |> split_list |>> split_list;
- val eqns' = eqns @
- map (prop_of #> HOLogic.dest_Trueprop #> HOLogic.dest_eq)
- (mem_Collect_eq :: split_conv :: to_pred_simps);
-
- (* predicate version of the introduction rules *)
- val intros' =
- map (fn (name_atts, t) => (name_atts,
- t |>
- map_aterms (fn u =>
- (case AList.lookup op = params' u of
- SOME (_, (u', _)) => u'
- | NONE => u)) |>
- Pattern.rewrite_term thy [] [to_pred_proc thy eqns'] |>
- eta_contract (member op = cs' orf is_pred pred_arities))) intros;
- val cnames_syn' = map (fn (b, _) => (Binding.suffix_name "p" b, NoSyn)) cnames_syn;
- val monos' = map (to_pred [] (Context.Proof ctxt)) monos;
- val ({preds, intrs, elims, raw_induct, ...}, ctxt1) =
- InductivePackage.add_ind_def
- {quiet_mode = quiet_mode, verbose = verbose, kind = kind, alt_name = Binding.empty,
- coind = coind, no_elim = no_elim, no_ind = no_ind,
- skip_mono = skip_mono, fork_mono = fork_mono}
- cs' intros' monos' params1 cnames_syn' ctxt;
-
- (* define inductive sets using previously defined predicates *)
- val (defs, ctxt2) = fold_map (LocalTheory.define Thm.internalK)
- (map (fn ((c_syn, (fs, U, _)), p) => (c_syn, (Attrib.empty_binding,
- fold_rev lambda params (HOLogic.Collect_const U $
- HOLogic.ap_split' fs U HOLogic.boolT (list_comb (p, params3))))))
- (cnames_syn ~~ cs_info ~~ preds)) ctxt1;
-
- (* prove theorems for converting predicate to set notation *)
- val ctxt3 = fold
- (fn (((p, c as Free (s, _)), (fs, U, Ts)), (_, (_, def))) => fn ctxt =>
- let val conv_thm =
- Goal.prove ctxt (map (fst o dest_Free) params) []
- (HOLogic.mk_Trueprop (HOLogic.mk_eq
- (list_comb (p, params3),
- list_abs (map (pair "x") Ts, HOLogic.mk_mem
- (HOLogic.mk_tuple' fs U (map Bound (length fs downto 0)),
- list_comb (c, params))))))
- (K (REPEAT (rtac ext 1) THEN simp_tac (HOL_basic_ss addsimps
- [def, mem_Collect_eq, split_conv]) 1))
- in
- ctxt |> LocalTheory.note kind ((Binding.name (s ^ "p_" ^ s ^ "_eq"),
- [Attrib.internal (K pred_set_conv_att)]),
- [conv_thm]) |> snd
- end) (preds ~~ cs ~~ cs_info ~~ defs) ctxt2;
-
- (* convert theorems to set notation *)
- val rec_name =
- if Binding.is_empty alt_name then
- Binding.name (space_implode "_" (map (Binding.name_of o fst) cnames_syn))
- else alt_name;
- val cnames = map (LocalTheory.full_name ctxt3 o #1) cnames_syn; (* FIXME *)
- val (intr_names, intr_atts) = split_list (map fst intros);
- val raw_induct' = to_set [] (Context.Proof ctxt3) raw_induct;
- val (intrs', elims', induct, ctxt4) =
- InductivePackage.declare_rules kind rec_name coind no_ind cnames
- (map (to_set [] (Context.Proof ctxt3)) intrs) intr_names intr_atts
- (map (fn th => (to_set [] (Context.Proof ctxt3) th,
- map fst (fst (RuleCases.get th)))) elims)
- raw_induct' ctxt3
- in
- ({intrs = intrs', elims = elims', induct = induct,
- raw_induct = raw_induct', preds = map fst defs},
- ctxt4)
- end;
-
-val add_inductive_i = InductivePackage.gen_add_inductive_i add_ind_set_def;
-val add_inductive = InductivePackage.gen_add_inductive add_ind_set_def;
-
-val mono_add_att = to_pred_att [] #> InductivePackage.mono_add;
-val mono_del_att = to_pred_att [] #> InductivePackage.mono_del;
-
-
-(** package setup **)
-
-(* setup theory *)
-
-val setup =
- Attrib.setup @{binding pred_set_conv} (Scan.succeed pred_set_conv_att)
- "declare rules for converting between predicate and set notation" #>
- Attrib.setup @{binding to_set} (Attrib.thms >> to_set_att) "convert rule to set notation" #>
- Attrib.setup @{binding to_pred} (Attrib.thms >> to_pred_att) "convert rule to predicate notation" #>
- Code.add_attribute ("ind_set",
- Scan.option (Args.$$$ "target" |-- Args.colon |-- Args.name) >> code_ind_att) #>
- Codegen.add_preprocessor codegen_preproc #>
- Attrib.setup @{binding mono_set} (Attrib.add_del mono_add_att mono_del_att)
- "declaration of monotonicity rule for set operators" #>
- Context.theory_map (Simplifier.map_ss (fn ss => ss addsimprocs [collect_mem_simproc]));
-
-
-(* outer syntax *)
-
-local structure P = OuterParse and K = OuterKeyword in
-
-val ind_set_decl = InductivePackage.gen_ind_decl add_ind_set_def;
-
-val _ =
- OuterSyntax.local_theory' "inductive_set" "define inductive sets" K.thy_decl (ind_set_decl false);
-
-val _ =
- OuterSyntax.local_theory' "coinductive_set" "define coinductive sets" K.thy_decl (ind_set_decl true);
-
-end;
-
-end;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/old_primrec.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,348 @@
+(* Title: HOL/Tools/old_primrec.ML
+ Author: Norbert Voelker, FernUni Hagen
+ Author: Stefan Berghofer, TU Muenchen
+
+Package for defining functions on datatypes by primitive recursion.
+*)
+
+signature OLD_PRIMREC =
+sig
+ val unify_consts: theory -> term list -> term list -> term list * term list
+ val add_primrec: string -> ((bstring * string) * Attrib.src list) list
+ -> theory -> thm list * theory
+ val add_primrec_unchecked: string -> ((bstring * string) * Attrib.src list) list
+ -> theory -> thm list * theory
+ val add_primrec_i: string -> ((bstring * term) * attribute list) list
+ -> theory -> thm list * theory
+ val add_primrec_unchecked_i: string -> ((bstring * term) * attribute list) list
+ -> theory -> thm list * theory
+end;
+
+structure OldPrimrec : OLD_PRIMREC =
+struct
+
+open DatatypeAux;
+
+exception RecError of string;
+
+fun primrec_err s = error ("Primrec definition error:\n" ^ s);
+fun primrec_eq_err thy s eq =
+ primrec_err (s ^ "\nin\n" ^ quote (Syntax.string_of_term_global thy eq));
+
+
+(*the following code ensures that each recursive set always has the
+ same type in all introduction rules*)
+fun unify_consts thy cs intr_ts =
+ (let
+ fun varify (t, (i, ts)) =
+ let val t' = map_types (Logic.incr_tvar (i + 1)) (snd (Type.varify [] t))
+ in (maxidx_of_term t', t'::ts) end;
+ val (i, cs') = List.foldr varify (~1, []) cs;
+ val (i', intr_ts') = List.foldr varify (i, []) intr_ts;
+ val rec_consts = fold Term.add_consts cs' [];
+ val intr_consts = fold Term.add_consts intr_ts' [];
+ fun unify (cname, cT) =
+ let val consts = map snd (filter (fn (c, _) => c = cname) intr_consts)
+ in fold (Sign.typ_unify thy) ((replicate (length consts) cT) ~~ consts) end;
+ val (env, _) = fold unify rec_consts (Vartab.empty, i');
+ val subst = Type.freeze o map_types (Envir.norm_type env)
+
+ in (map subst cs', map subst intr_ts')
+ end) handle Type.TUNIFY =>
+ (warning "Occurrences of recursive constant have non-unifiable types"; (cs, intr_ts));
+
+
+(* preprocessing of equations *)
+
+fun process_eqn thy eq rec_fns =
+ let
+ val (lhs, rhs) =
+ if null (Term.add_vars eq []) then
+ HOLogic.dest_eq (HOLogic.dest_Trueprop eq)
+ handle TERM _ => raise RecError "not a proper equation"
+ else raise RecError "illegal schematic variable(s)";
+
+ val (recfun, args) = strip_comb lhs;
+ val fnameT = dest_Const recfun handle TERM _ =>
+ raise RecError "function is not declared as constant in theory";
+
+ val (ls', rest) = take_prefix is_Free args;
+ val (middle, rs') = take_suffix is_Free rest;
+ val rpos = length ls';
+
+ val (constr, cargs') = if null middle then raise RecError "constructor missing"
+ else strip_comb (hd middle);
+ val (cname, T) = dest_Const constr
+ handle TERM _ => raise RecError "ill-formed constructor";
+ val (tname, _) = dest_Type (body_type T) handle TYPE _ =>
+ raise RecError "cannot determine datatype associated with function"
+
+ val (ls, cargs, rs) =
+ (map dest_Free ls', map dest_Free cargs', map dest_Free rs')
+ handle TERM _ => raise RecError "illegal argument in pattern";
+ val lfrees = ls @ rs @ cargs;
+
+ fun check_vars _ [] = ()
+ | check_vars s vars = raise RecError (s ^ commas_quote (map fst vars))
+ in
+ if length middle > 1 then
+ raise RecError "more than one non-variable in pattern"
+ else
+ (check_vars "repeated variable names in pattern: " (duplicates (op =) lfrees);
+ check_vars "extra variables on rhs: "
+ (map dest_Free (OldTerm.term_frees rhs) \\ lfrees);
+ case AList.lookup (op =) rec_fns fnameT of
+ NONE =>
+ (fnameT, (tname, rpos, [(cname, (ls, cargs, rs, rhs, eq))]))::rec_fns
+ | SOME (_, rpos', eqns) =>
+ if AList.defined (op =) eqns cname then
+ raise RecError "constructor already occurred as pattern"
+ else if rpos <> rpos' then
+ raise RecError "position of recursive argument inconsistent"
+ else
+ AList.update (op =) (fnameT, (tname, rpos, (cname, (ls, cargs, rs, rhs, eq))::eqns))
+ rec_fns)
+ end
+ handle RecError s => primrec_eq_err thy s eq;
+
+fun process_fun thy descr rec_eqns (i, fnameT as (fname, _)) (fnameTs, fnss) =
+ let
+ val (_, (tname, _, constrs)) = List.nth (descr, i);
+
+ (* substitute "fname ls x rs" by "y ls rs" for (x, (_, y)) in subs *)
+
+ fun subst [] t fs = (t, fs)
+ | subst subs (Abs (a, T, t)) fs =
+ fs
+ |> subst subs t
+ |-> (fn t' => pair (Abs (a, T, t')))
+ | subst subs (t as (_ $ _)) fs =
+ let
+ val (f, ts) = strip_comb t;
+ in
+ if is_Const f andalso dest_Const f mem map fst rec_eqns then
+ let
+ val fnameT' as (fname', _) = dest_Const f;
+ val (_, rpos, _) = the (AList.lookup (op =) rec_eqns fnameT');
+ val ls = Library.take (rpos, ts);
+ val rest = Library.drop (rpos, ts);
+ val (x', rs) = (hd rest, tl rest)
+ handle Empty => raise RecError ("not enough arguments\
+ \ in recursive application\nof function " ^ quote fname' ^ " on rhs");
+ val (x, xs) = strip_comb x'
+ in case AList.lookup (op =) subs x
+ of NONE =>
+ fs
+ |> fold_map (subst subs) ts
+ |-> (fn ts' => pair (list_comb (f, ts')))
+ | SOME (i', y) =>
+ fs
+ |> fold_map (subst subs) (xs @ ls @ rs)
+ ||> process_fun thy descr rec_eqns (i', fnameT')
+ |-> (fn ts' => pair (list_comb (y, ts')))
+ end
+ else
+ fs
+ |> fold_map (subst subs) (f :: ts)
+ |-> (fn (f'::ts') => pair (list_comb (f', ts')))
+ end
+ | subst _ t fs = (t, fs);
+
+ (* translate rec equations into function arguments suitable for rec comb *)
+
+ fun trans eqns (cname, cargs) (fnameTs', fnss', fns) =
+ (case AList.lookup (op =) eqns cname of
+ NONE => (warning ("No equation for constructor " ^ quote cname ^
+ "\nin definition of function " ^ quote fname);
+ (fnameTs', fnss', (Const ("HOL.undefined", dummyT))::fns))
+ | SOME (ls, cargs', rs, rhs, eq) =>
+ let
+ val recs = filter (is_rec_type o snd) (cargs' ~~ cargs);
+ val rargs = map fst recs;
+ val subs = map (rpair dummyT o fst)
+ (rev (Term.rename_wrt_term rhs rargs));
+ val (rhs', (fnameTs'', fnss'')) =
+ (subst (map (fn ((x, y), z) =>
+ (Free x, (body_index y, Free z)))
+ (recs ~~ subs)) rhs (fnameTs', fnss'))
+ handle RecError s => primrec_eq_err thy s eq
+ in (fnameTs'', fnss'',
+ (list_abs_free (cargs' @ subs @ ls @ rs, rhs'))::fns)
+ end)
+
+ in (case AList.lookup (op =) fnameTs i of
+ NONE =>
+ if exists (equal fnameT o snd) fnameTs then
+ raise RecError ("inconsistent functions for datatype " ^ quote tname)
+ else
+ let
+ val (_, _, eqns) = the (AList.lookup (op =) rec_eqns fnameT);
+ val (fnameTs', fnss', fns) = fold_rev (trans eqns) constrs
+ ((i, fnameT)::fnameTs, fnss, [])
+ in
+ (fnameTs', (i, (fname, #1 (snd (hd eqns)), fns))::fnss')
+ end
+ | SOME fnameT' =>
+ if fnameT = fnameT' then (fnameTs, fnss)
+ else raise RecError ("inconsistent functions for datatype " ^ quote tname))
+ end;
+
+
+(* prepare functions needed for definitions *)
+
+fun get_fns fns ((i : int, (tname, _, constrs)), rec_name) (fs, defs) =
+ case AList.lookup (op =) fns i of
+ NONE =>
+ let
+ val dummy_fns = map (fn (_, cargs) => Const ("HOL.undefined",
+ replicate ((length cargs) + (length (List.filter is_rec_type cargs)))
+ dummyT ---> HOLogic.unitT)) constrs;
+ val _ = warning ("No function definition for datatype " ^ quote tname)
+ in
+ (dummy_fns @ fs, defs)
+ end
+ | SOME (fname, ls, fs') => (fs' @ fs, (fname, ls, rec_name, tname) :: defs);
+
+
+(* make definition *)
+
+fun make_def thy fs (fname, ls, rec_name, tname) =
+ let
+ val rhs = fold_rev (fn T => fn t => Abs ("", T, t))
+ ((map snd ls) @ [dummyT])
+ (list_comb (Const (rec_name, dummyT),
+ fs @ map Bound (0 ::(length ls downto 1))))
+ val def_name = Long_Name.base_name fname ^ "_" ^ Long_Name.base_name tname ^ "_def";
+ val def_prop =
+ singleton (Syntax.check_terms (ProofContext.init thy))
+ (Logic.mk_equals (Const (fname, dummyT), rhs));
+ in (def_name, def_prop) end;
+
+
+(* find datatypes which contain all datatypes in tnames' *)
+
+fun find_dts (dt_info : datatype_info Symtab.table) _ [] = []
+ | find_dts dt_info tnames' (tname::tnames) =
+ (case Symtab.lookup dt_info tname of
+ NONE => primrec_err (quote tname ^ " is not a datatype")
+ | SOME dt =>
+ if tnames' subset (map (#1 o snd) (#descr dt)) then
+ (tname, dt)::(find_dts dt_info tnames' tnames)
+ else find_dts dt_info tnames' tnames);
+
+fun prepare_induct ({descr, induction, ...}: datatype_info) rec_eqns =
+ let
+ fun constrs_of (_, (_, _, cs)) =
+ map (fn (cname:string, (_, cargs, _, _, _)) => (cname, map fst cargs)) cs;
+ val params_of = these o AList.lookup (op =) (List.concat (map constrs_of rec_eqns));
+ in
+ induction
+ |> RuleCases.rename_params (map params_of (List.concat (map (map #1 o #3 o #2) descr)))
+ |> RuleCases.save induction
+ end;
+
+local
+
+fun gen_primrec_i note def alt_name eqns_atts thy =
+ let
+ val (eqns, atts) = split_list eqns_atts;
+ val dt_info = Datatype.get_datatypes thy;
+ val rec_eqns = fold_rev (process_eqn thy o snd) eqns [] ;
+ val tnames = distinct (op =) (map (#1 o snd) rec_eqns);
+ val dts = find_dts dt_info tnames tnames;
+ val main_fns =
+ map (fn (tname, {index, ...}) =>
+ (index,
+ (fst o the o find_first (fn f => (#1 o snd) f = tname)) rec_eqns))
+ dts;
+ val {descr, rec_names, rec_rewrites, ...} =
+ if null dts then
+ primrec_err ("datatypes " ^ commas_quote tnames ^ "\nare not mutually recursive")
+ else snd (hd dts);
+ val (fnameTs, fnss) =
+ fold_rev (process_fun thy descr rec_eqns) main_fns ([], []);
+ val (fs, defs) = fold_rev (get_fns fnss) (descr ~~ rec_names) ([], []);
+ val defs' = map (make_def thy fs) defs;
+ val nameTs1 = map snd fnameTs;
+ val nameTs2 = map fst rec_eqns;
+ val _ = if gen_eq_set (op =) (nameTs1, nameTs2) then ()
+ else primrec_err ("functions " ^ commas_quote (map fst nameTs2) ^
+ "\nare not mutually recursive");
+ val primrec_name =
+ if alt_name = "" then (space_implode "_" (map (Long_Name.base_name o #1) defs)) else alt_name;
+ val (defs_thms', thy') =
+ thy
+ |> Sign.add_path primrec_name
+ |> fold_map def (map (fn (name, t) => ((name, []), t)) defs');
+ val rewrites = (map mk_meta_eq rec_rewrites) @ map snd defs_thms';
+ val simps = map (fn (_, t) => Goal.prove_global thy' [] [] t
+ (fn _ => EVERY [rewrite_goals_tac rewrites, rtac refl 1])) eqns;
+ val (simps', thy'') =
+ thy'
+ |> fold_map note ((map fst eqns ~~ atts) ~~ map single simps);
+ val simps'' = maps snd simps';
+ in
+ thy''
+ |> note (("simps", [Simplifier.simp_add, Nitpick_Const_Simp_Thms.add,
+ Code.add_default_eqn_attribute]), simps'')
+ |> snd
+ |> note (("induct", []), [prepare_induct (#2 (hd dts)) rec_eqns])
+ |> snd
+ |> Sign.parent_path
+ |> pair simps''
+ end;
+
+fun gen_primrec note def alt_name eqns thy =
+ let
+ val ((names, strings), srcss) = apfst split_list (split_list eqns);
+ val atts = map (map (Attrib.attribute thy)) srcss;
+ val eqn_ts = map (fn s => Syntax.read_prop_global thy s
+ handle ERROR msg => cat_error msg ("The error(s) above occurred for " ^ s)) strings;
+ val rec_ts = map (fn eq => head_of (fst (HOLogic.dest_eq (HOLogic.dest_Trueprop eq)))
+ handle TERM _ => primrec_eq_err thy "not a proper equation" eq) eqn_ts;
+ val (_, eqn_ts') = unify_consts thy rec_ts eqn_ts
+ in
+ gen_primrec_i note def alt_name (names ~~ eqn_ts' ~~ atts) thy
+ end;
+
+fun thy_note ((name, atts), thms) =
+ PureThy.add_thmss [((Binding.name name, thms), atts)] #-> (fn [thms] => pair (name, thms));
+fun thy_def false ((name, atts), t) =
+ PureThy.add_defs false [((Binding.name name, t), atts)] #-> (fn [thm] => pair (name, thm))
+ | thy_def true ((name, atts), t) =
+ PureThy.add_defs_unchecked false [((Binding.name name, t), atts)] #-> (fn [thm] => pair (name, thm));
+
+in
+
+val add_primrec = gen_primrec thy_note (thy_def false);
+val add_primrec_unchecked = gen_primrec thy_note (thy_def true);
+val add_primrec_i = gen_primrec_i thy_note (thy_def false);
+val add_primrec_unchecked_i = gen_primrec_i thy_note (thy_def true);
+fun gen_primrec note def alt_name specs =
+ gen_primrec_i note def alt_name (map (fn ((name, t), atts) => ((name, atts), t)) specs);
+
+end;
+
+
+(* see primrec.ML (* outer syntax *)
+
+local structure P = OuterParse and K = OuterKeyword in
+
+val opt_unchecked_name =
+ Scan.optional (P.$$$ "(" |-- P.!!!
+ (((P.$$$ "unchecked" >> K true) -- Scan.optional P.name "" ||
+ P.name >> pair false) --| P.$$$ ")")) (false, "");
+
+val primrec_decl =
+ opt_unchecked_name -- Scan.repeat1 (SpecParse.opt_thm_name ":" -- P.prop);
+
+val _ =
+ OuterSyntax.command "primrec" "define primitive recursive functions on datatypes" K.thy_decl
+ (primrec_decl >> (fn ((unchecked, alt_name), eqns) =>
+ Toplevel.theory (snd o
+ (if unchecked then add_primrec_unchecked else add_primrec) alt_name
+ (map P.triple_swap eqns))));
+
+end;*)
+
+end;
--- a/src/HOL/Tools/old_primrec_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,348 +0,0 @@
-(* Title: HOL/Tools/old_primrec_package.ML
- Author: Norbert Voelker, FernUni Hagen
- Author: Stefan Berghofer, TU Muenchen
-
-Package for defining functions on datatypes by primitive recursion.
-*)
-
-signature OLD_PRIMREC_PACKAGE =
-sig
- val unify_consts: theory -> term list -> term list -> term list * term list
- val add_primrec: string -> ((bstring * string) * Attrib.src list) list
- -> theory -> thm list * theory
- val add_primrec_unchecked: string -> ((bstring * string) * Attrib.src list) list
- -> theory -> thm list * theory
- val add_primrec_i: string -> ((bstring * term) * attribute list) list
- -> theory -> thm list * theory
- val add_primrec_unchecked_i: string -> ((bstring * term) * attribute list) list
- -> theory -> thm list * theory
-end;
-
-structure OldPrimrecPackage : OLD_PRIMREC_PACKAGE =
-struct
-
-open DatatypeAux;
-
-exception RecError of string;
-
-fun primrec_err s = error ("Primrec definition error:\n" ^ s);
-fun primrec_eq_err thy s eq =
- primrec_err (s ^ "\nin\n" ^ quote (Syntax.string_of_term_global thy eq));
-
-
-(*the following code ensures that each recursive set always has the
- same type in all introduction rules*)
-fun unify_consts thy cs intr_ts =
- (let
- fun varify (t, (i, ts)) =
- let val t' = map_types (Logic.incr_tvar (i + 1)) (snd (Type.varify [] t))
- in (maxidx_of_term t', t'::ts) end;
- val (i, cs') = List.foldr varify (~1, []) cs;
- val (i', intr_ts') = List.foldr varify (i, []) intr_ts;
- val rec_consts = fold Term.add_consts cs' [];
- val intr_consts = fold Term.add_consts intr_ts' [];
- fun unify (cname, cT) =
- let val consts = map snd (filter (fn (c, _) => c = cname) intr_consts)
- in fold (Sign.typ_unify thy) ((replicate (length consts) cT) ~~ consts) end;
- val (env, _) = fold unify rec_consts (Vartab.empty, i');
- val subst = Type.freeze o map_types (Envir.norm_type env)
-
- in (map subst cs', map subst intr_ts')
- end) handle Type.TUNIFY =>
- (warning "Occurrences of recursive constant have non-unifiable types"; (cs, intr_ts));
-
-
-(* preprocessing of equations *)
-
-fun process_eqn thy eq rec_fns =
- let
- val (lhs, rhs) =
- if null (Term.add_vars eq []) then
- HOLogic.dest_eq (HOLogic.dest_Trueprop eq)
- handle TERM _ => raise RecError "not a proper equation"
- else raise RecError "illegal schematic variable(s)";
-
- val (recfun, args) = strip_comb lhs;
- val fnameT = dest_Const recfun handle TERM _ =>
- raise RecError "function is not declared as constant in theory";
-
- val (ls', rest) = take_prefix is_Free args;
- val (middle, rs') = take_suffix is_Free rest;
- val rpos = length ls';
-
- val (constr, cargs') = if null middle then raise RecError "constructor missing"
- else strip_comb (hd middle);
- val (cname, T) = dest_Const constr
- handle TERM _ => raise RecError "ill-formed constructor";
- val (tname, _) = dest_Type (body_type T) handle TYPE _ =>
- raise RecError "cannot determine datatype associated with function"
-
- val (ls, cargs, rs) =
- (map dest_Free ls', map dest_Free cargs', map dest_Free rs')
- handle TERM _ => raise RecError "illegal argument in pattern";
- val lfrees = ls @ rs @ cargs;
-
- fun check_vars _ [] = ()
- | check_vars s vars = raise RecError (s ^ commas_quote (map fst vars))
- in
- if length middle > 1 then
- raise RecError "more than one non-variable in pattern"
- else
- (check_vars "repeated variable names in pattern: " (duplicates (op =) lfrees);
- check_vars "extra variables on rhs: "
- (map dest_Free (OldTerm.term_frees rhs) \\ lfrees);
- case AList.lookup (op =) rec_fns fnameT of
- NONE =>
- (fnameT, (tname, rpos, [(cname, (ls, cargs, rs, rhs, eq))]))::rec_fns
- | SOME (_, rpos', eqns) =>
- if AList.defined (op =) eqns cname then
- raise RecError "constructor already occurred as pattern"
- else if rpos <> rpos' then
- raise RecError "position of recursive argument inconsistent"
- else
- AList.update (op =) (fnameT, (tname, rpos, (cname, (ls, cargs, rs, rhs, eq))::eqns))
- rec_fns)
- end
- handle RecError s => primrec_eq_err thy s eq;
-
-fun process_fun thy descr rec_eqns (i, fnameT as (fname, _)) (fnameTs, fnss) =
- let
- val (_, (tname, _, constrs)) = List.nth (descr, i);
-
- (* substitute "fname ls x rs" by "y ls rs" for (x, (_, y)) in subs *)
-
- fun subst [] t fs = (t, fs)
- | subst subs (Abs (a, T, t)) fs =
- fs
- |> subst subs t
- |-> (fn t' => pair (Abs (a, T, t')))
- | subst subs (t as (_ $ _)) fs =
- let
- val (f, ts) = strip_comb t;
- in
- if is_Const f andalso dest_Const f mem map fst rec_eqns then
- let
- val fnameT' as (fname', _) = dest_Const f;
- val (_, rpos, _) = the (AList.lookup (op =) rec_eqns fnameT');
- val ls = Library.take (rpos, ts);
- val rest = Library.drop (rpos, ts);
- val (x', rs) = (hd rest, tl rest)
- handle Empty => raise RecError ("not enough arguments\
- \ in recursive application\nof function " ^ quote fname' ^ " on rhs");
- val (x, xs) = strip_comb x'
- in case AList.lookup (op =) subs x
- of NONE =>
- fs
- |> fold_map (subst subs) ts
- |-> (fn ts' => pair (list_comb (f, ts')))
- | SOME (i', y) =>
- fs
- |> fold_map (subst subs) (xs @ ls @ rs)
- ||> process_fun thy descr rec_eqns (i', fnameT')
- |-> (fn ts' => pair (list_comb (y, ts')))
- end
- else
- fs
- |> fold_map (subst subs) (f :: ts)
- |-> (fn (f'::ts') => pair (list_comb (f', ts')))
- end
- | subst _ t fs = (t, fs);
-
- (* translate rec equations into function arguments suitable for rec comb *)
-
- fun trans eqns (cname, cargs) (fnameTs', fnss', fns) =
- (case AList.lookup (op =) eqns cname of
- NONE => (warning ("No equation for constructor " ^ quote cname ^
- "\nin definition of function " ^ quote fname);
- (fnameTs', fnss', (Const ("HOL.undefined", dummyT))::fns))
- | SOME (ls, cargs', rs, rhs, eq) =>
- let
- val recs = filter (is_rec_type o snd) (cargs' ~~ cargs);
- val rargs = map fst recs;
- val subs = map (rpair dummyT o fst)
- (rev (Term.rename_wrt_term rhs rargs));
- val (rhs', (fnameTs'', fnss'')) =
- (subst (map (fn ((x, y), z) =>
- (Free x, (body_index y, Free z)))
- (recs ~~ subs)) rhs (fnameTs', fnss'))
- handle RecError s => primrec_eq_err thy s eq
- in (fnameTs'', fnss'',
- (list_abs_free (cargs' @ subs @ ls @ rs, rhs'))::fns)
- end)
-
- in (case AList.lookup (op =) fnameTs i of
- NONE =>
- if exists (equal fnameT o snd) fnameTs then
- raise RecError ("inconsistent functions for datatype " ^ quote tname)
- else
- let
- val (_, _, eqns) = the (AList.lookup (op =) rec_eqns fnameT);
- val (fnameTs', fnss', fns) = fold_rev (trans eqns) constrs
- ((i, fnameT)::fnameTs, fnss, [])
- in
- (fnameTs', (i, (fname, #1 (snd (hd eqns)), fns))::fnss')
- end
- | SOME fnameT' =>
- if fnameT = fnameT' then (fnameTs, fnss)
- else raise RecError ("inconsistent functions for datatype " ^ quote tname))
- end;
-
-
-(* prepare functions needed for definitions *)
-
-fun get_fns fns ((i : int, (tname, _, constrs)), rec_name) (fs, defs) =
- case AList.lookup (op =) fns i of
- NONE =>
- let
- val dummy_fns = map (fn (_, cargs) => Const ("HOL.undefined",
- replicate ((length cargs) + (length (List.filter is_rec_type cargs)))
- dummyT ---> HOLogic.unitT)) constrs;
- val _ = warning ("No function definition for datatype " ^ quote tname)
- in
- (dummy_fns @ fs, defs)
- end
- | SOME (fname, ls, fs') => (fs' @ fs, (fname, ls, rec_name, tname) :: defs);
-
-
-(* make definition *)
-
-fun make_def thy fs (fname, ls, rec_name, tname) =
- let
- val rhs = fold_rev (fn T => fn t => Abs ("", T, t))
- ((map snd ls) @ [dummyT])
- (list_comb (Const (rec_name, dummyT),
- fs @ map Bound (0 ::(length ls downto 1))))
- val def_name = Long_Name.base_name fname ^ "_" ^ Long_Name.base_name tname ^ "_def";
- val def_prop =
- singleton (Syntax.check_terms (ProofContext.init thy))
- (Logic.mk_equals (Const (fname, dummyT), rhs));
- in (def_name, def_prop) end;
-
-
-(* find datatypes which contain all datatypes in tnames' *)
-
-fun find_dts (dt_info : datatype_info Symtab.table) _ [] = []
- | find_dts dt_info tnames' (tname::tnames) =
- (case Symtab.lookup dt_info tname of
- NONE => primrec_err (quote tname ^ " is not a datatype")
- | SOME dt =>
- if tnames' subset (map (#1 o snd) (#descr dt)) then
- (tname, dt)::(find_dts dt_info tnames' tnames)
- else find_dts dt_info tnames' tnames);
-
-fun prepare_induct ({descr, induction, ...}: datatype_info) rec_eqns =
- let
- fun constrs_of (_, (_, _, cs)) =
- map (fn (cname:string, (_, cargs, _, _, _)) => (cname, map fst cargs)) cs;
- val params_of = these o AList.lookup (op =) (List.concat (map constrs_of rec_eqns));
- in
- induction
- |> RuleCases.rename_params (map params_of (List.concat (map (map #1 o #3 o #2) descr)))
- |> RuleCases.save induction
- end;
-
-local
-
-fun gen_primrec_i note def alt_name eqns_atts thy =
- let
- val (eqns, atts) = split_list eqns_atts;
- val dt_info = DatatypePackage.get_datatypes thy;
- val rec_eqns = fold_rev (process_eqn thy o snd) eqns [] ;
- val tnames = distinct (op =) (map (#1 o snd) rec_eqns);
- val dts = find_dts dt_info tnames tnames;
- val main_fns =
- map (fn (tname, {index, ...}) =>
- (index,
- (fst o the o find_first (fn f => (#1 o snd) f = tname)) rec_eqns))
- dts;
- val {descr, rec_names, rec_rewrites, ...} =
- if null dts then
- primrec_err ("datatypes " ^ commas_quote tnames ^ "\nare not mutually recursive")
- else snd (hd dts);
- val (fnameTs, fnss) =
- fold_rev (process_fun thy descr rec_eqns) main_fns ([], []);
- val (fs, defs) = fold_rev (get_fns fnss) (descr ~~ rec_names) ([], []);
- val defs' = map (make_def thy fs) defs;
- val nameTs1 = map snd fnameTs;
- val nameTs2 = map fst rec_eqns;
- val _ = if gen_eq_set (op =) (nameTs1, nameTs2) then ()
- else primrec_err ("functions " ^ commas_quote (map fst nameTs2) ^
- "\nare not mutually recursive");
- val primrec_name =
- if alt_name = "" then (space_implode "_" (map (Long_Name.base_name o #1) defs)) else alt_name;
- val (defs_thms', thy') =
- thy
- |> Sign.add_path primrec_name
- |> fold_map def (map (fn (name, t) => ((name, []), t)) defs');
- val rewrites = (map mk_meta_eq rec_rewrites) @ map snd defs_thms';
- val simps = map (fn (_, t) => Goal.prove_global thy' [] [] t
- (fn _ => EVERY [rewrite_goals_tac rewrites, rtac refl 1])) eqns;
- val (simps', thy'') =
- thy'
- |> fold_map note ((map fst eqns ~~ atts) ~~ map single simps);
- val simps'' = maps snd simps';
- in
- thy''
- |> note (("simps", [Simplifier.simp_add, Nitpick_Const_Simp_Thms.add,
- Code.add_default_eqn_attribute]), simps'')
- |> snd
- |> note (("induct", []), [prepare_induct (#2 (hd dts)) rec_eqns])
- |> snd
- |> Sign.parent_path
- |> pair simps''
- end;
-
-fun gen_primrec note def alt_name eqns thy =
- let
- val ((names, strings), srcss) = apfst split_list (split_list eqns);
- val atts = map (map (Attrib.attribute thy)) srcss;
- val eqn_ts = map (fn s => Syntax.read_prop_global thy s
- handle ERROR msg => cat_error msg ("The error(s) above occurred for " ^ s)) strings;
- val rec_ts = map (fn eq => head_of (fst (HOLogic.dest_eq (HOLogic.dest_Trueprop eq)))
- handle TERM _ => primrec_eq_err thy "not a proper equation" eq) eqn_ts;
- val (_, eqn_ts') = unify_consts thy rec_ts eqn_ts
- in
- gen_primrec_i note def alt_name (names ~~ eqn_ts' ~~ atts) thy
- end;
-
-fun thy_note ((name, atts), thms) =
- PureThy.add_thmss [((Binding.name name, thms), atts)] #-> (fn [thms] => pair (name, thms));
-fun thy_def false ((name, atts), t) =
- PureThy.add_defs false [((Binding.name name, t), atts)] #-> (fn [thm] => pair (name, thm))
- | thy_def true ((name, atts), t) =
- PureThy.add_defs_unchecked false [((Binding.name name, t), atts)] #-> (fn [thm] => pair (name, thm));
-
-in
-
-val add_primrec = gen_primrec thy_note (thy_def false);
-val add_primrec_unchecked = gen_primrec thy_note (thy_def true);
-val add_primrec_i = gen_primrec_i thy_note (thy_def false);
-val add_primrec_unchecked_i = gen_primrec_i thy_note (thy_def true);
-fun gen_primrec note def alt_name specs =
- gen_primrec_i note def alt_name (map (fn ((name, t), atts) => ((name, atts), t)) specs);
-
-end;
-
-
-(* see primrecr_package.ML (* outer syntax *)
-
-local structure P = OuterParse and K = OuterKeyword in
-
-val opt_unchecked_name =
- Scan.optional (P.$$$ "(" |-- P.!!!
- (((P.$$$ "unchecked" >> K true) -- Scan.optional P.name "" ||
- P.name >> pair false) --| P.$$$ ")")) (false, "");
-
-val primrec_decl =
- opt_unchecked_name -- Scan.repeat1 (SpecParse.opt_thm_name ":" -- P.prop);
-
-val _ =
- OuterSyntax.command "primrec" "define primitive recursive functions on datatypes" K.thy_decl
- (primrec_decl >> (fn ((unchecked, alt_name), eqns) =>
- Toplevel.theory (snd o
- (if unchecked then add_primrec_unchecked else add_primrec) alt_name
- (map P.triple_swap eqns))));
-
-end;*)
-
-end;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/primrec.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,332 @@
+(* Title: HOL/Tools/primrec.ML
+ Author: Stefan Berghofer, TU Muenchen; Norbert Voelker, FernUni Hagen;
+ Florian Haftmann, TU Muenchen
+
+Package for defining functions on datatypes by primitive recursion.
+*)
+
+signature PRIMREC =
+sig
+ val add_primrec: (binding * typ option * mixfix) list ->
+ (Attrib.binding * term) list -> local_theory -> thm list * local_theory
+ val add_primrec_cmd: (binding * string option * mixfix) list ->
+ (Attrib.binding * string) list -> local_theory -> thm list * local_theory
+ val add_primrec_global: (binding * typ option * mixfix) list ->
+ (Attrib.binding * term) list -> theory -> thm list * theory
+ val add_primrec_overloaded: (string * (string * typ) * bool) list ->
+ (binding * typ option * mixfix) list ->
+ (Attrib.binding * term) list -> theory -> thm list * theory
+ val add_primrec_simple: ((binding * typ) * mixfix) list -> term list ->
+ local_theory -> (string * thm list list) * local_theory
+end;
+
+structure Primrec : PRIMREC =
+struct
+
+open DatatypeAux;
+
+exception PrimrecError of string * term option;
+
+fun primrec_error msg = raise PrimrecError (msg, NONE);
+fun primrec_error_eqn msg eqn = raise PrimrecError (msg, SOME eqn);
+
+fun message s = if ! Toplevel.debug then tracing s else ();
+
+
+(* preprocessing of equations *)
+
+fun process_eqn is_fixed spec rec_fns =
+ let
+ val (vs, Ts) = split_list (strip_qnt_vars "all" spec);
+ val body = strip_qnt_body "all" spec;
+ val (vs', _) = Name.variants vs (Name.make_context (fold_aterms
+ (fn Free (v, _) => insert (op =) v | _ => I) body []));
+ val eqn = curry subst_bounds (map2 (curry Free) vs' Ts |> rev) body;
+ val (lhs, rhs) = HOLogic.dest_eq (HOLogic.dest_Trueprop eqn)
+ handle TERM _ => primrec_error "not a proper equation";
+ val (recfun, args) = strip_comb lhs;
+ val fname = case recfun of Free (v, _) => if is_fixed v then v
+ else primrec_error "illegal head of function equation"
+ | _ => primrec_error "illegal head of function equation";
+
+ val (ls', rest) = take_prefix is_Free args;
+ val (middle, rs') = take_suffix is_Free rest;
+ val rpos = length ls';
+
+ val (constr, cargs') = if null middle then primrec_error "constructor missing"
+ else strip_comb (hd middle);
+ val (cname, T) = dest_Const constr
+ handle TERM _ => primrec_error "ill-formed constructor";
+ val (tname, _) = dest_Type (body_type T) handle TYPE _ =>
+ primrec_error "cannot determine datatype associated with function"
+
+ val (ls, cargs, rs) =
+ (map dest_Free ls', map dest_Free cargs', map dest_Free rs')
+ handle TERM _ => primrec_error "illegal argument in pattern";
+ val lfrees = ls @ rs @ cargs;
+
+ fun check_vars _ [] = ()
+ | check_vars s vars = primrec_error (s ^ commas_quote (map fst vars)) eqn;
+ in
+ if length middle > 1 then
+ primrec_error "more than one non-variable in pattern"
+ else
+ (check_vars "repeated variable names in pattern: " (duplicates (op =) lfrees);
+ check_vars "extra variables on rhs: "
+ (map dest_Free (OldTerm.term_frees rhs) |> subtract (op =) lfrees
+ |> filter_out (is_fixed o fst));
+ case AList.lookup (op =) rec_fns fname of
+ NONE =>
+ (fname, (tname, rpos, [(cname, (ls, cargs, rs, rhs, eqn))]))::rec_fns
+ | SOME (_, rpos', eqns) =>
+ if AList.defined (op =) eqns cname then
+ primrec_error "constructor already occurred as pattern"
+ else if rpos <> rpos' then
+ primrec_error "position of recursive argument inconsistent"
+ else
+ AList.update (op =)
+ (fname, (tname, rpos, (cname, (ls, cargs, rs, rhs, eqn))::eqns))
+ rec_fns)
+ end handle PrimrecError (msg, NONE) => primrec_error_eqn msg spec;
+
+fun process_fun descr eqns (i, fname) (fnames, fnss) =
+ let
+ val (_, (tname, _, constrs)) = nth descr i;
+
+ (* substitute "fname ls x rs" by "y ls rs" for (x, (_, y)) in subs *)
+
+ fun subst [] t fs = (t, fs)
+ | subst subs (Abs (a, T, t)) fs =
+ fs
+ |> subst subs t
+ |-> (fn t' => pair (Abs (a, T, t')))
+ | subst subs (t as (_ $ _)) fs =
+ let
+ val (f, ts) = strip_comb t;
+ in
+ if is_Free f
+ andalso member (fn ((v, _), (w, _)) => v = w) eqns (dest_Free f) then
+ let
+ val (fname', _) = dest_Free f;
+ val (_, rpos, _) = the (AList.lookup (op =) eqns fname');
+ val (ls, rs) = chop rpos ts
+ val (x', rs') = case rs
+ of x' :: rs => (x', rs)
+ | [] => primrec_error ("not enough arguments in recursive application\n"
+ ^ "of function " ^ quote fname' ^ " on rhs");
+ val (x, xs) = strip_comb x';
+ in case AList.lookup (op =) subs x
+ of NONE =>
+ fs
+ |> fold_map (subst subs) ts
+ |-> (fn ts' => pair (list_comb (f, ts')))
+ | SOME (i', y) =>
+ fs
+ |> fold_map (subst subs) (xs @ ls @ rs')
+ ||> process_fun descr eqns (i', fname')
+ |-> (fn ts' => pair (list_comb (y, ts')))
+ end
+ else
+ fs
+ |> fold_map (subst subs) (f :: ts)
+ |-> (fn (f'::ts') => pair (list_comb (f', ts')))
+ end
+ | subst _ t fs = (t, fs);
+
+ (* translate rec equations into function arguments suitable for rec comb *)
+
+ fun trans eqns (cname, cargs) (fnames', fnss', fns) =
+ (case AList.lookup (op =) eqns cname of
+ NONE => (warning ("No equation for constructor " ^ quote cname ^
+ "\nin definition of function " ^ quote fname);
+ (fnames', fnss', (Const ("HOL.undefined", dummyT))::fns))
+ | SOME (ls, cargs', rs, rhs, eq) =>
+ let
+ val recs = filter (is_rec_type o snd) (cargs' ~~ cargs);
+ val rargs = map fst recs;
+ val subs = map (rpair dummyT o fst)
+ (rev (Term.rename_wrt_term rhs rargs));
+ val (rhs', (fnames'', fnss'')) = subst (map2 (fn (x, y) => fn z =>
+ (Free x, (body_index y, Free z))) recs subs) rhs (fnames', fnss')
+ handle PrimrecError (s, NONE) => primrec_error_eqn s eq
+ in (fnames'', fnss'',
+ (list_abs_free (cargs' @ subs @ ls @ rs, rhs'))::fns)
+ end)
+
+ in (case AList.lookup (op =) fnames i of
+ NONE =>
+ if exists (fn (_, v) => fname = v) fnames then
+ primrec_error ("inconsistent functions for datatype " ^ quote tname)
+ else
+ let
+ val (_, _, eqns) = the (AList.lookup (op =) eqns fname);
+ val (fnames', fnss', fns) = fold_rev (trans eqns) constrs
+ ((i, fname)::fnames, fnss, [])
+ in
+ (fnames', (i, (fname, #1 (snd (hd eqns)), fns))::fnss')
+ end
+ | SOME fname' =>
+ if fname = fname' then (fnames, fnss)
+ else primrec_error ("inconsistent functions for datatype " ^ quote tname))
+ end;
+
+
+(* prepare functions needed for definitions *)
+
+fun get_fns fns ((i : int, (tname, _, constrs)), rec_name) (fs, defs) =
+ case AList.lookup (op =) fns i of
+ NONE =>
+ let
+ val dummy_fns = map (fn (_, cargs) => Const ("HOL.undefined",
+ replicate ((length cargs) + (length (List.filter is_rec_type cargs)))
+ dummyT ---> HOLogic.unitT)) constrs;
+ val _ = warning ("No function definition for datatype " ^ quote tname)
+ in
+ (dummy_fns @ fs, defs)
+ end
+ | SOME (fname, ls, fs') => (fs' @ fs, (fname, ls, rec_name, tname) :: defs);
+
+
+(* make definition *)
+
+fun make_def ctxt fixes fs (fname, ls, rec_name, tname) =
+ let
+ val SOME (var, varT) = get_first (fn ((b, T), mx) =>
+ if Binding.name_of b = fname then SOME ((b, mx), T) else NONE) fixes;
+ val def_name = Thm.def_name (Long_Name.base_name fname);
+ val raw_rhs = fold_rev (fn T => fn t => Abs ("", T, t)) (map snd ls @ [dummyT])
+ (list_comb (Const (rec_name, dummyT), fs @ map Bound (0 :: (length ls downto 1))))
+ val rhs = singleton (Syntax.check_terms ctxt)
+ (TypeInfer.constrain varT raw_rhs);
+ in (var, ((Binding.name def_name, []), rhs)) end;
+
+
+(* find datatypes which contain all datatypes in tnames' *)
+
+fun find_dts (dt_info : datatype_info Symtab.table) _ [] = []
+ | find_dts dt_info tnames' (tname::tnames) =
+ (case Symtab.lookup dt_info tname of
+ NONE => primrec_error (quote tname ^ " is not a datatype")
+ | SOME dt =>
+ if tnames' subset (map (#1 o snd) (#descr dt)) then
+ (tname, dt)::(find_dts dt_info tnames' tnames)
+ else find_dts dt_info tnames' tnames);
+
+
+(* distill primitive definition(s) from primrec specification *)
+
+fun distill lthy fixes eqs =
+ let
+ val eqns = fold_rev (process_eqn (fn v => Variable.is_fixed lthy v
+ orelse exists (fn ((w, _), _) => v = Binding.name_of w) fixes)) eqs [];
+ val tnames = distinct (op =) (map (#1 o snd) eqns);
+ val dts = find_dts (Datatype.get_datatypes (ProofContext.theory_of lthy)) tnames tnames;
+ val main_fns = map (fn (tname, {index, ...}) =>
+ (index, (fst o the o find_first (fn (_, x) => #1 x = tname)) eqns)) dts;
+ val {descr, rec_names, rec_rewrites, ...} =
+ if null dts then primrec_error
+ ("datatypes " ^ commas_quote tnames ^ "\nare not mutually recursive")
+ else snd (hd dts);
+ val (fnames, fnss) = fold_rev (process_fun descr eqns) main_fns ([], []);
+ val (fs, raw_defs) = fold_rev (get_fns fnss) (descr ~~ rec_names) ([], []);
+ val defs = map (make_def lthy fixes fs) raw_defs;
+ val names = map snd fnames;
+ val names_eqns = map fst eqns;
+ val _ = if gen_eq_set (op =) (names, names_eqns) then ()
+ else primrec_error ("functions " ^ commas_quote names_eqns ^
+ "\nare not mutually recursive");
+ val rec_rewrites' = map mk_meta_eq rec_rewrites;
+ val prefix = space_implode "_" (map (Long_Name.base_name o #1) raw_defs);
+ fun prove lthy defs =
+ let
+ val rewrites = rec_rewrites' @ map (snd o snd) defs;
+ fun tac _ = EVERY [rewrite_goals_tac rewrites, rtac refl 1];
+ val _ = message ("Proving equations for primrec function(s) " ^ commas_quote names);
+ in map (fn eq => [Goal.prove lthy [] [] eq tac]) eqs end;
+ in ((prefix, (fs, defs)), prove) end
+ handle PrimrecError (msg, some_eqn) =>
+ error ("Primrec definition error:\n" ^ msg ^ (case some_eqn
+ of SOME eqn => "\nin\n" ^ quote (Syntax.string_of_term lthy eqn)
+ | NONE => ""));
+
+
+(* primrec definition *)
+
+fun add_primrec_simple fixes ts lthy =
+ let
+ val ((prefix, (fs, defs)), prove) = distill lthy fixes ts;
+ in
+ lthy
+ |> fold_map (LocalTheory.define Thm.definitionK) defs
+ |-> (fn defs => `(fn lthy => (prefix, prove lthy defs)))
+ end;
+
+local
+
+fun gen_primrec set_group prep_spec raw_fixes raw_spec lthy =
+ let
+ val (fixes, spec) = fst (prep_spec raw_fixes raw_spec lthy);
+ fun attr_bindings prefix = map (fn ((b, attrs), _) =>
+ (Binding.qualify false prefix b, Code.add_default_eqn_attrib :: attrs)) spec;
+ fun simp_attr_binding prefix = (Binding.qualify true prefix (Binding.name "simps"),
+ map (Attrib.internal o K)
+ [Simplifier.simp_add, Nitpick_Const_Simp_Thms.add, Quickcheck_RecFun_Simp_Thms.add]);
+ in
+ lthy
+ |> set_group ? LocalTheory.set_group (serial_string ())
+ |> add_primrec_simple fixes (map snd spec)
+ |-> (fn (prefix, simps) => fold_map (LocalTheory.note Thm.generatedK)
+ (attr_bindings prefix ~~ simps)
+ #-> (fn simps' => LocalTheory.note Thm.generatedK
+ (simp_attr_binding prefix, maps snd simps')))
+ |>> snd
+ end;
+
+in
+
+val add_primrec = gen_primrec false Specification.check_spec;
+val add_primrec_cmd = gen_primrec true Specification.read_spec;
+
+end;
+
+fun add_primrec_global fixes specs thy =
+ let
+ val lthy = TheoryTarget.init NONE thy;
+ val (simps, lthy') = add_primrec fixes specs lthy;
+ val simps' = ProofContext.export lthy' lthy simps;
+ in (simps', LocalTheory.exit_global lthy') end;
+
+fun add_primrec_overloaded ops fixes specs thy =
+ let
+ val lthy = TheoryTarget.overloading ops thy;
+ val (simps, lthy') = add_primrec fixes specs lthy;
+ val simps' = ProofContext.export lthy' lthy simps;
+ in (simps', LocalTheory.exit_global lthy') end;
+
+
+(* outer syntax *)
+
+local structure P = OuterParse and K = OuterKeyword in
+
+val opt_unchecked_name =
+ Scan.optional (P.$$$ "(" |-- P.!!!
+ (((P.$$$ "unchecked" >> K true) -- Scan.optional P.name "" ||
+ P.name >> pair false) --| P.$$$ ")")) (false, "");
+
+val old_primrec_decl =
+ opt_unchecked_name -- Scan.repeat1 ((SpecParse.opt_thm_name ":" >> apfst Binding.name_of) -- P.prop);
+
+val primrec_decl = P.opt_target -- P.fixes -- SpecParse.where_alt_specs;
+
+val _ =
+ OuterSyntax.command "primrec" "define primitive recursive functions on datatypes" K.thy_decl
+ ((primrec_decl >> (fn ((opt_target, fixes), specs) =>
+ Toplevel.local_theory opt_target (add_primrec_cmd fixes specs #> snd)))
+ || (old_primrec_decl >> (fn ((unchecked, alt_name), eqns) =>
+ Toplevel.theory (snd o
+ (if unchecked then OldPrimrec.add_primrec_unchecked else OldPrimrec.add_primrec)
+ alt_name (map P.triple_swap eqns)))));
+
+end;
+
+end;
--- a/src/HOL/Tools/primrec_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,332 +0,0 @@
-(* Title: HOL/Tools/primrec_package.ML
- Author: Stefan Berghofer, TU Muenchen; Norbert Voelker, FernUni Hagen;
- Florian Haftmann, TU Muenchen
-
-Package for defining functions on datatypes by primitive recursion.
-*)
-
-signature PRIMREC_PACKAGE =
-sig
- val add_primrec: (binding * typ option * mixfix) list ->
- (Attrib.binding * term) list -> local_theory -> thm list * local_theory
- val add_primrec_cmd: (binding * string option * mixfix) list ->
- (Attrib.binding * string) list -> local_theory -> thm list * local_theory
- val add_primrec_global: (binding * typ option * mixfix) list ->
- (Attrib.binding * term) list -> theory -> thm list * theory
- val add_primrec_overloaded: (string * (string * typ) * bool) list ->
- (binding * typ option * mixfix) list ->
- (Attrib.binding * term) list -> theory -> thm list * theory
- val add_primrec_simple: ((binding * typ) * mixfix) list -> term list ->
- local_theory -> (string * thm list list) * local_theory
-end;
-
-structure PrimrecPackage : PRIMREC_PACKAGE =
-struct
-
-open DatatypeAux;
-
-exception PrimrecError of string * term option;
-
-fun primrec_error msg = raise PrimrecError (msg, NONE);
-fun primrec_error_eqn msg eqn = raise PrimrecError (msg, SOME eqn);
-
-fun message s = if ! Toplevel.debug then tracing s else ();
-
-
-(* preprocessing of equations *)
-
-fun process_eqn is_fixed spec rec_fns =
- let
- val (vs, Ts) = split_list (strip_qnt_vars "all" spec);
- val body = strip_qnt_body "all" spec;
- val (vs', _) = Name.variants vs (Name.make_context (fold_aterms
- (fn Free (v, _) => insert (op =) v | _ => I) body []));
- val eqn = curry subst_bounds (map2 (curry Free) vs' Ts |> rev) body;
- val (lhs, rhs) = HOLogic.dest_eq (HOLogic.dest_Trueprop eqn)
- handle TERM _ => primrec_error "not a proper equation";
- val (recfun, args) = strip_comb lhs;
- val fname = case recfun of Free (v, _) => if is_fixed v then v
- else primrec_error "illegal head of function equation"
- | _ => primrec_error "illegal head of function equation";
-
- val (ls', rest) = take_prefix is_Free args;
- val (middle, rs') = take_suffix is_Free rest;
- val rpos = length ls';
-
- val (constr, cargs') = if null middle then primrec_error "constructor missing"
- else strip_comb (hd middle);
- val (cname, T) = dest_Const constr
- handle TERM _ => primrec_error "ill-formed constructor";
- val (tname, _) = dest_Type (body_type T) handle TYPE _ =>
- primrec_error "cannot determine datatype associated with function"
-
- val (ls, cargs, rs) =
- (map dest_Free ls', map dest_Free cargs', map dest_Free rs')
- handle TERM _ => primrec_error "illegal argument in pattern";
- val lfrees = ls @ rs @ cargs;
-
- fun check_vars _ [] = ()
- | check_vars s vars = primrec_error (s ^ commas_quote (map fst vars)) eqn;
- in
- if length middle > 1 then
- primrec_error "more than one non-variable in pattern"
- else
- (check_vars "repeated variable names in pattern: " (duplicates (op =) lfrees);
- check_vars "extra variables on rhs: "
- (map dest_Free (OldTerm.term_frees rhs) |> subtract (op =) lfrees
- |> filter_out (is_fixed o fst));
- case AList.lookup (op =) rec_fns fname of
- NONE =>
- (fname, (tname, rpos, [(cname, (ls, cargs, rs, rhs, eqn))]))::rec_fns
- | SOME (_, rpos', eqns) =>
- if AList.defined (op =) eqns cname then
- primrec_error "constructor already occurred as pattern"
- else if rpos <> rpos' then
- primrec_error "position of recursive argument inconsistent"
- else
- AList.update (op =)
- (fname, (tname, rpos, (cname, (ls, cargs, rs, rhs, eqn))::eqns))
- rec_fns)
- end handle PrimrecError (msg, NONE) => primrec_error_eqn msg spec;
-
-fun process_fun descr eqns (i, fname) (fnames, fnss) =
- let
- val (_, (tname, _, constrs)) = nth descr i;
-
- (* substitute "fname ls x rs" by "y ls rs" for (x, (_, y)) in subs *)
-
- fun subst [] t fs = (t, fs)
- | subst subs (Abs (a, T, t)) fs =
- fs
- |> subst subs t
- |-> (fn t' => pair (Abs (a, T, t')))
- | subst subs (t as (_ $ _)) fs =
- let
- val (f, ts) = strip_comb t;
- in
- if is_Free f
- andalso member (fn ((v, _), (w, _)) => v = w) eqns (dest_Free f) then
- let
- val (fname', _) = dest_Free f;
- val (_, rpos, _) = the (AList.lookup (op =) eqns fname');
- val (ls, rs) = chop rpos ts
- val (x', rs') = case rs
- of x' :: rs => (x', rs)
- | [] => primrec_error ("not enough arguments in recursive application\n"
- ^ "of function " ^ quote fname' ^ " on rhs");
- val (x, xs) = strip_comb x';
- in case AList.lookup (op =) subs x
- of NONE =>
- fs
- |> fold_map (subst subs) ts
- |-> (fn ts' => pair (list_comb (f, ts')))
- | SOME (i', y) =>
- fs
- |> fold_map (subst subs) (xs @ ls @ rs')
- ||> process_fun descr eqns (i', fname')
- |-> (fn ts' => pair (list_comb (y, ts')))
- end
- else
- fs
- |> fold_map (subst subs) (f :: ts)
- |-> (fn (f'::ts') => pair (list_comb (f', ts')))
- end
- | subst _ t fs = (t, fs);
-
- (* translate rec equations into function arguments suitable for rec comb *)
-
- fun trans eqns (cname, cargs) (fnames', fnss', fns) =
- (case AList.lookup (op =) eqns cname of
- NONE => (warning ("No equation for constructor " ^ quote cname ^
- "\nin definition of function " ^ quote fname);
- (fnames', fnss', (Const ("HOL.undefined", dummyT))::fns))
- | SOME (ls, cargs', rs, rhs, eq) =>
- let
- val recs = filter (is_rec_type o snd) (cargs' ~~ cargs);
- val rargs = map fst recs;
- val subs = map (rpair dummyT o fst)
- (rev (Term.rename_wrt_term rhs rargs));
- val (rhs', (fnames'', fnss'')) = subst (map2 (fn (x, y) => fn z =>
- (Free x, (body_index y, Free z))) recs subs) rhs (fnames', fnss')
- handle PrimrecError (s, NONE) => primrec_error_eqn s eq
- in (fnames'', fnss'',
- (list_abs_free (cargs' @ subs @ ls @ rs, rhs'))::fns)
- end)
-
- in (case AList.lookup (op =) fnames i of
- NONE =>
- if exists (fn (_, v) => fname = v) fnames then
- primrec_error ("inconsistent functions for datatype " ^ quote tname)
- else
- let
- val (_, _, eqns) = the (AList.lookup (op =) eqns fname);
- val (fnames', fnss', fns) = fold_rev (trans eqns) constrs
- ((i, fname)::fnames, fnss, [])
- in
- (fnames', (i, (fname, #1 (snd (hd eqns)), fns))::fnss')
- end
- | SOME fname' =>
- if fname = fname' then (fnames, fnss)
- else primrec_error ("inconsistent functions for datatype " ^ quote tname))
- end;
-
-
-(* prepare functions needed for definitions *)
-
-fun get_fns fns ((i : int, (tname, _, constrs)), rec_name) (fs, defs) =
- case AList.lookup (op =) fns i of
- NONE =>
- let
- val dummy_fns = map (fn (_, cargs) => Const ("HOL.undefined",
- replicate ((length cargs) + (length (List.filter is_rec_type cargs)))
- dummyT ---> HOLogic.unitT)) constrs;
- val _ = warning ("No function definition for datatype " ^ quote tname)
- in
- (dummy_fns @ fs, defs)
- end
- | SOME (fname, ls, fs') => (fs' @ fs, (fname, ls, rec_name, tname) :: defs);
-
-
-(* make definition *)
-
-fun make_def ctxt fixes fs (fname, ls, rec_name, tname) =
- let
- val SOME (var, varT) = get_first (fn ((b, T), mx) =>
- if Binding.name_of b = fname then SOME ((b, mx), T) else NONE) fixes;
- val def_name = Thm.def_name (Long_Name.base_name fname);
- val raw_rhs = fold_rev (fn T => fn t => Abs ("", T, t)) (map snd ls @ [dummyT])
- (list_comb (Const (rec_name, dummyT), fs @ map Bound (0 :: (length ls downto 1))))
- val rhs = singleton (Syntax.check_terms ctxt)
- (TypeInfer.constrain varT raw_rhs);
- in (var, ((Binding.name def_name, []), rhs)) end;
-
-
-(* find datatypes which contain all datatypes in tnames' *)
-
-fun find_dts (dt_info : datatype_info Symtab.table) _ [] = []
- | find_dts dt_info tnames' (tname::tnames) =
- (case Symtab.lookup dt_info tname of
- NONE => primrec_error (quote tname ^ " is not a datatype")
- | SOME dt =>
- if tnames' subset (map (#1 o snd) (#descr dt)) then
- (tname, dt)::(find_dts dt_info tnames' tnames)
- else find_dts dt_info tnames' tnames);
-
-
-(* distill primitive definition(s) from primrec specification *)
-
-fun distill lthy fixes eqs =
- let
- val eqns = fold_rev (process_eqn (fn v => Variable.is_fixed lthy v
- orelse exists (fn ((w, _), _) => v = Binding.name_of w) fixes)) eqs [];
- val tnames = distinct (op =) (map (#1 o snd) eqns);
- val dts = find_dts (DatatypePackage.get_datatypes (ProofContext.theory_of lthy)) tnames tnames;
- val main_fns = map (fn (tname, {index, ...}) =>
- (index, (fst o the o find_first (fn (_, x) => #1 x = tname)) eqns)) dts;
- val {descr, rec_names, rec_rewrites, ...} =
- if null dts then primrec_error
- ("datatypes " ^ commas_quote tnames ^ "\nare not mutually recursive")
- else snd (hd dts);
- val (fnames, fnss) = fold_rev (process_fun descr eqns) main_fns ([], []);
- val (fs, raw_defs) = fold_rev (get_fns fnss) (descr ~~ rec_names) ([], []);
- val defs = map (make_def lthy fixes fs) raw_defs;
- val names = map snd fnames;
- val names_eqns = map fst eqns;
- val _ = if gen_eq_set (op =) (names, names_eqns) then ()
- else primrec_error ("functions " ^ commas_quote names_eqns ^
- "\nare not mutually recursive");
- val rec_rewrites' = map mk_meta_eq rec_rewrites;
- val prefix = space_implode "_" (map (Long_Name.base_name o #1) raw_defs);
- fun prove lthy defs =
- let
- val rewrites = rec_rewrites' @ map (snd o snd) defs;
- fun tac _ = EVERY [rewrite_goals_tac rewrites, rtac refl 1];
- val _ = message ("Proving equations for primrec function(s) " ^ commas_quote names);
- in map (fn eq => [Goal.prove lthy [] [] eq tac]) eqs end;
- in ((prefix, (fs, defs)), prove) end
- handle PrimrecError (msg, some_eqn) =>
- error ("Primrec definition error:\n" ^ msg ^ (case some_eqn
- of SOME eqn => "\nin\n" ^ quote (Syntax.string_of_term lthy eqn)
- | NONE => ""));
-
-
-(* primrec definition *)
-
-fun add_primrec_simple fixes ts lthy =
- let
- val ((prefix, (fs, defs)), prove) = distill lthy fixes ts;
- in
- lthy
- |> fold_map (LocalTheory.define Thm.definitionK) defs
- |-> (fn defs => `(fn lthy => (prefix, prove lthy defs)))
- end;
-
-local
-
-fun gen_primrec set_group prep_spec raw_fixes raw_spec lthy =
- let
- val (fixes, spec) = fst (prep_spec raw_fixes raw_spec lthy);
- fun attr_bindings prefix = map (fn ((b, attrs), _) =>
- (Binding.qualify false prefix b, Code.add_default_eqn_attrib :: attrs)) spec;
- fun simp_attr_binding prefix = (Binding.qualify true prefix (Binding.name "simps"),
- map (Attrib.internal o K)
- [Simplifier.simp_add, Nitpick_Const_Simp_Thms.add, Quickcheck_RecFun_Simp_Thms.add]);
- in
- lthy
- |> set_group ? LocalTheory.set_group (serial_string ())
- |> add_primrec_simple fixes (map snd spec)
- |-> (fn (prefix, simps) => fold_map (LocalTheory.note Thm.generatedK)
- (attr_bindings prefix ~~ simps)
- #-> (fn simps' => LocalTheory.note Thm.generatedK
- (simp_attr_binding prefix, maps snd simps')))
- |>> snd
- end;
-
-in
-
-val add_primrec = gen_primrec false Specification.check_spec;
-val add_primrec_cmd = gen_primrec true Specification.read_spec;
-
-end;
-
-fun add_primrec_global fixes specs thy =
- let
- val lthy = TheoryTarget.init NONE thy;
- val (simps, lthy') = add_primrec fixes specs lthy;
- val simps' = ProofContext.export lthy' lthy simps;
- in (simps', LocalTheory.exit_global lthy') end;
-
-fun add_primrec_overloaded ops fixes specs thy =
- let
- val lthy = TheoryTarget.overloading ops thy;
- val (simps, lthy') = add_primrec fixes specs lthy;
- val simps' = ProofContext.export lthy' lthy simps;
- in (simps', LocalTheory.exit_global lthy') end;
-
-
-(* outer syntax *)
-
-local structure P = OuterParse and K = OuterKeyword in
-
-val opt_unchecked_name =
- Scan.optional (P.$$$ "(" |-- P.!!!
- (((P.$$$ "unchecked" >> K true) -- Scan.optional P.name "" ||
- P.name >> pair false) --| P.$$$ ")")) (false, "");
-
-val old_primrec_decl =
- opt_unchecked_name -- Scan.repeat1 ((SpecParse.opt_thm_name ":" >> apfst Binding.name_of) -- P.prop);
-
-val primrec_decl = P.opt_target -- P.fixes -- SpecParse.where_alt_specs;
-
-val _ =
- OuterSyntax.command "primrec" "define primitive recursive functions on datatypes" K.thy_decl
- ((primrec_decl >> (fn ((opt_target, fixes), specs) =>
- Toplevel.local_theory opt_target (add_primrec_cmd fixes specs #> snd)))
- || (old_primrec_decl >> (fn ((unchecked, alt_name), eqns) =>
- Toplevel.theory (snd o
- (if unchecked then OldPrimrecPackage.add_primrec_unchecked else OldPrimrecPackage.add_primrec)
- alt_name (map P.triple_swap eqns)))));
-
-end;
-
-end;
--- a/src/HOL/Tools/quickcheck_generators.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/quickcheck_generators.ML Fri Jun 19 21:08:07 2009 +0200
@@ -122,7 +122,7 @@
fun ensure_random_typecopy tyco thy =
let
val SOME { vs = raw_vs, constr, typ = raw_typ, ... } =
- TypecopyPackage.get_info thy tyco;
+ Typecopy.get_info thy tyco;
val constrain = curry (Sorts.inter_sort (Sign.classes_of thy));
val typ = map_atyps (fn TFree (v, sort) =>
TFree (v, constrain sort @{sort random})) raw_typ;
@@ -168,7 +168,7 @@
val t_rhs = lambda t_k proto_t_rhs;
val eqs0 = [subst_v @{term "0::code_numeral"} eq, subst_v (@{term "Suc_code_numeral"} $ t_k) eq];
val eqs1 = map (Pattern.rewrite_term thy rew_ts []) eqs0;
- val ((_, eqs2), lthy') = PrimrecPackage.add_primrec_simple
+ val ((_, eqs2), lthy') = Primrec.add_primrec_simple
[((Binding.name random_aux, T), NoSyn)] eqs1 lthy;
val eq_tac = ALLGOALS (simp_tac rew_ss)
THEN (ALLGOALS (ProofContext.fact_tac (flat eqs2)));
@@ -361,7 +361,7 @@
val pp = Syntax.pp_global thy;
val algebra = Sign.classes_of thy;
val (descr, raw_vs, tycos, (names, auxnames), raw_TUs) =
- DatatypePackage.the_datatype_descr thy raw_tycos;
+ Datatype.the_datatype_descr thy raw_tycos;
val random_insts = (map (rpair @{sort random}) o flat o maps snd o maps snd)
(DatatypeAux.interpret_construction descr raw_vs { atyp = single, dtyp = (K o K o K) [] });
val term_of_insts = (map (rpair @{sort term_of}) o flat o maps snd o maps snd)
@@ -381,7 +381,7 @@
val setup = Code_Target.extend_target (target, (Code_ML.target_Eval, K I))
#> Quickcheck.add_generator ("code", compile_generator_expr o ProofContext.theory_of)
- #> TypecopyPackage.interpretation ensure_random_typecopy
- #> DatatypePackage.interpretation ensure_random_datatype;
+ #> Typecopy.interpretation ensure_random_typecopy
+ #> Datatype.interpretation ensure_random_datatype;
end;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/recdef.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,331 @@
+(* Title: HOL/Tools/recdef.ML
+ Author: Markus Wenzel, TU Muenchen
+
+Wrapper module for Konrad Slind's TFL package.
+*)
+
+signature RECDEF =
+sig
+ val get_recdef: theory -> string
+ -> {simps: thm list, rules: thm list list, induct: thm, tcs: term list} option
+ val get_hints: Proof.context -> {simps: thm list, congs: (string * thm) list, wfs: thm list}
+ val simp_add: attribute
+ val simp_del: attribute
+ val cong_add: attribute
+ val cong_del: attribute
+ val wf_add: attribute
+ val wf_del: attribute
+ val add_recdef: bool -> xstring -> string -> ((binding * string) * Attrib.src list) list ->
+ Attrib.src option -> theory -> theory
+ * {simps: thm list, rules: thm list list, induct: thm, tcs: term list}
+ val add_recdef_i: bool -> xstring -> term -> ((binding * term) * attribute list) list ->
+ theory -> theory * {simps: thm list, rules: thm list list, induct: thm, tcs: term list}
+ val defer_recdef: xstring -> string list -> (Facts.ref * Attrib.src list) list
+ -> theory -> theory * {induct_rules: thm}
+ val defer_recdef_i: xstring -> term list -> thm list -> theory -> theory * {induct_rules: thm}
+ val recdef_tc: bstring * Attrib.src list -> xstring -> int option -> bool ->
+ local_theory -> Proof.state
+ val recdef_tc_i: bstring * Attrib.src list -> string -> int option -> bool ->
+ local_theory -> Proof.state
+ val setup: theory -> theory
+end;
+
+structure Recdef: RECDEF =
+struct
+
+
+(** recdef hints **)
+
+(* type hints *)
+
+type hints = {simps: thm list, congs: (string * thm) list, wfs: thm list};
+
+fun mk_hints (simps, congs, wfs) = {simps = simps, congs = congs, wfs = wfs}: hints;
+fun map_hints f ({simps, congs, wfs}: hints) = mk_hints (f (simps, congs, wfs));
+
+fun map_simps f = map_hints (fn (simps, congs, wfs) => (f simps, congs, wfs));
+fun map_congs f = map_hints (fn (simps, congs, wfs) => (simps, f congs, wfs));
+fun map_wfs f = map_hints (fn (simps, congs, wfs) => (simps, congs, f wfs));
+
+fun pretty_hints ({simps, congs, wfs}: hints) =
+ [Pretty.big_list "recdef simp hints:" (map Display.pretty_thm simps),
+ Pretty.big_list "recdef cong hints:" (map Display.pretty_thm (map snd congs)),
+ Pretty.big_list "recdef wf hints:" (map Display.pretty_thm wfs)];
+
+
+(* congruence rules *)
+
+local
+
+val cong_head =
+ fst o Term.dest_Const o Term.head_of o fst o Logic.dest_equals o Thm.concl_of;
+
+fun prep_cong raw_thm =
+ let val thm = safe_mk_meta_eq raw_thm in (cong_head thm, thm) end;
+
+in
+
+fun add_cong raw_thm congs =
+ let
+ val (c, thm) = prep_cong raw_thm;
+ val _ = if AList.defined (op =) congs c
+ then warning ("Overwriting recdef congruence rule for " ^ quote c)
+ else ();
+ in AList.update (op =) (c, thm) congs end;
+
+fun del_cong raw_thm congs =
+ let
+ val (c, thm) = prep_cong raw_thm;
+ val _ = if AList.defined (op =) congs c
+ then ()
+ else warning ("No recdef congruence rule for " ^ quote c);
+ in AList.delete (op =) c congs end;
+
+end;
+
+
+
+(** global and local recdef data **)
+
+(* theory data *)
+
+type recdef_info = {simps: thm list, rules: thm list list, induct: thm, tcs: term list};
+
+structure GlobalRecdefData = TheoryDataFun
+(
+ type T = recdef_info Symtab.table * hints;
+ val empty = (Symtab.empty, mk_hints ([], [], [])): T;
+ val copy = I;
+ val extend = I;
+ fun merge _
+ ((tab1, {simps = simps1, congs = congs1, wfs = wfs1}),
+ (tab2, {simps = simps2, congs = congs2, wfs = wfs2})) : T =
+ (Symtab.merge (K true) (tab1, tab2),
+ mk_hints (Thm.merge_thms (simps1, simps2),
+ AList.merge (op =) Thm.eq_thm (congs1, congs2),
+ Thm.merge_thms (wfs1, wfs2)));
+);
+
+val get_recdef = Symtab.lookup o #1 o GlobalRecdefData.get;
+
+fun put_recdef name info thy =
+ let
+ val (tab, hints) = GlobalRecdefData.get thy;
+ val tab' = Symtab.update_new (name, info) tab
+ handle Symtab.DUP _ => error ("Duplicate recursive function definition " ^ quote name);
+ in GlobalRecdefData.put (tab', hints) thy end;
+
+val get_global_hints = #2 o GlobalRecdefData.get;
+
+
+(* proof data *)
+
+structure LocalRecdefData = ProofDataFun
+(
+ type T = hints;
+ val init = get_global_hints;
+);
+
+val get_hints = LocalRecdefData.get;
+fun map_hints f = Context.mapping (GlobalRecdefData.map (apsnd f)) (LocalRecdefData.map f);
+
+
+(* attributes *)
+
+fun attrib f = Thm.declaration_attribute (map_hints o f);
+
+val simp_add = attrib (map_simps o Thm.add_thm);
+val simp_del = attrib (map_simps o Thm.del_thm);
+val cong_add = attrib (map_congs o add_cong);
+val cong_del = attrib (map_congs o del_cong);
+val wf_add = attrib (map_wfs o Thm.add_thm);
+val wf_del = attrib (map_wfs o Thm.del_thm);
+
+
+(* modifiers *)
+
+val recdef_simpN = "recdef_simp";
+val recdef_congN = "recdef_cong";
+val recdef_wfN = "recdef_wf";
+
+val recdef_modifiers =
+ [Args.$$$ recdef_simpN -- Args.colon >> K ((I, simp_add): Method.modifier),
+ Args.$$$ recdef_simpN -- Args.add -- Args.colon >> K (I, simp_add),
+ Args.$$$ recdef_simpN -- Args.del -- Args.colon >> K (I, simp_del),
+ Args.$$$ recdef_congN -- Args.colon >> K (I, cong_add),
+ Args.$$$ recdef_congN -- Args.add -- Args.colon >> K (I, cong_add),
+ Args.$$$ recdef_congN -- Args.del -- Args.colon >> K (I, cong_del),
+ Args.$$$ recdef_wfN -- Args.colon >> K (I, wf_add),
+ Args.$$$ recdef_wfN -- Args.add -- Args.colon >> K (I, wf_add),
+ Args.$$$ recdef_wfN -- Args.del -- Args.colon >> K (I, wf_del)] @
+ Clasimp.clasimp_modifiers;
+
+
+
+(** prepare_hints(_i) **)
+
+fun prepare_hints thy opt_src =
+ let
+ val ctxt0 = ProofContext.init thy;
+ val ctxt =
+ (case opt_src of
+ NONE => ctxt0
+ | SOME src => #2 (Method.syntax (Method.sections recdef_modifiers) src ctxt0));
+ val {simps, congs, wfs} = get_hints ctxt;
+ val cs = local_claset_of ctxt;
+ val ss = local_simpset_of ctxt addsimps simps;
+ in (cs, ss, rev (map snd congs), wfs) end;
+
+fun prepare_hints_i thy () =
+ let
+ val ctxt0 = ProofContext.init thy;
+ val {simps, congs, wfs} = get_global_hints thy;
+ in (local_claset_of ctxt0, local_simpset_of ctxt0 addsimps simps, rev (map snd congs), wfs) end;
+
+
+
+(** add_recdef(_i) **)
+
+fun requires_recdef thy = Theory.requires thy "Recdef" "recursive functions";
+
+fun gen_add_recdef tfl_fn prep_att prep_hints not_permissive raw_name R eq_srcs hints thy =
+ let
+ val _ = requires_recdef thy;
+
+ val name = Sign.intern_const thy raw_name;
+ val bname = Long_Name.base_name name;
+ val _ = writeln ("Defining recursive function " ^ quote name ^ " ...");
+
+ val ((eq_names, eqs), raw_eq_atts) = apfst split_list (split_list eq_srcs);
+ val eq_atts = map (map (prep_att thy)) raw_eq_atts;
+
+ val (cs, ss, congs, wfs) = prep_hints thy hints;
+ (*We must remove imp_cong to prevent looping when the induction rule
+ is simplified. Many induction rules have nested implications that would
+ give rise to looping conditional rewriting.*)
+ val (thy, {rules = rules_idx, induct, tcs}) =
+ tfl_fn not_permissive thy cs (ss delcongs [imp_cong])
+ congs wfs name R eqs;
+ val rules = (map o map) fst (partition_eq (eq_snd (op = : int * int -> bool)) rules_idx);
+ val simp_att = if null tcs then [Simplifier.simp_add, Nitpick_Const_Simp_Thms.add,
+ Code.add_default_eqn_attribute, Quickcheck_RecFun_Simp_Thms.add] else [];
+
+ val ((simps' :: rules', [induct']), thy) =
+ thy
+ |> Sign.add_path bname
+ |> PureThy.add_thmss
+ (((Binding.name "simps", List.concat rules), simp_att) :: ((eq_names ~~ rules) ~~ eq_atts))
+ ||>> PureThy.add_thms [((Binding.name "induct", induct), [])];
+ val result = {simps = simps', rules = rules', induct = induct', tcs = tcs};
+ val thy =
+ thy
+ |> put_recdef name result
+ |> Sign.parent_path;
+ in (thy, result) end;
+
+val add_recdef = gen_add_recdef Tfl.define Attrib.attribute prepare_hints;
+fun add_recdef_i x y z w = gen_add_recdef Tfl.define_i (K I) prepare_hints_i x y z w ();
+
+
+
+(** defer_recdef(_i) **)
+
+fun gen_defer_recdef tfl_fn eval_thms raw_name eqs raw_congs thy =
+ let
+ val name = Sign.intern_const thy raw_name;
+ val bname = Long_Name.base_name name;
+
+ val _ = requires_recdef thy;
+ val _ = writeln ("Deferred recursive function " ^ quote name ^ " ...");
+
+ val congs = eval_thms (ProofContext.init thy) raw_congs;
+ val (thy2, induct_rules) = tfl_fn thy congs name eqs;
+ val ([induct_rules'], thy3) =
+ thy2
+ |> Sign.add_path bname
+ |> PureThy.add_thms [((Binding.name "induct_rules", induct_rules), [])]
+ ||> Sign.parent_path;
+ in (thy3, {induct_rules = induct_rules'}) end;
+
+val defer_recdef = gen_defer_recdef Tfl.defer Attrib.eval_thms;
+val defer_recdef_i = gen_defer_recdef Tfl.defer_i (K I);
+
+
+
+(** recdef_tc(_i) **)
+
+fun gen_recdef_tc prep_att prep_name (bname, raw_atts) raw_name opt_i int lthy =
+ let
+ val thy = ProofContext.theory_of lthy;
+ val name = prep_name thy raw_name;
+ val atts = map (prep_att thy) raw_atts;
+ val tcs =
+ (case get_recdef thy name of
+ NONE => error ("No recdef definition of constant: " ^ quote name)
+ | SOME {tcs, ...} => tcs);
+ val i = the_default 1 opt_i;
+ val tc = nth tcs (i - 1) handle Subscript =>
+ error ("No termination condition #" ^ string_of_int i ^
+ " in recdef definition of " ^ quote name);
+ in
+ Specification.theorem Thm.internalK NONE (K I) (Binding.name bname, atts)
+ [] (Element.Shows [(Attrib.empty_binding, [(HOLogic.mk_Trueprop tc, [])])]) int lthy
+ end;
+
+val recdef_tc = gen_recdef_tc Attrib.intern_src Sign.intern_const;
+val recdef_tc_i = gen_recdef_tc (K I) (K I);
+
+
+
+(** package setup **)
+
+(* setup theory *)
+
+val setup =
+ Attrib.setup @{binding recdef_simp} (Attrib.add_del simp_add simp_del)
+ "declaration of recdef simp rule" #>
+ Attrib.setup @{binding recdef_cong} (Attrib.add_del cong_add cong_del)
+ "declaration of recdef cong rule" #>
+ Attrib.setup @{binding recdef_wf} (Attrib.add_del wf_add wf_del)
+ "declaration of recdef wf rule";
+
+
+(* outer syntax *)
+
+local structure P = OuterParse and K = OuterKeyword in
+
+val _ = List.app OuterKeyword.keyword ["permissive", "congs", "hints"];
+
+val hints =
+ P.$$$ "(" |-- P.!!! (P.position (P.$$$ "hints" -- Args.parse) --| P.$$$ ")") >> Args.src;
+
+val recdef_decl =
+ Scan.optional (P.$$$ "(" -- P.!!! (P.$$$ "permissive" -- P.$$$ ")") >> K false) true --
+ P.name -- P.term -- Scan.repeat1 (SpecParse.opt_thm_name ":" -- P.prop)
+ -- Scan.option hints
+ >> (fn ((((p, f), R), eqs), src) => #1 o add_recdef p f R (map P.triple_swap eqs) src);
+
+val _ =
+ OuterSyntax.command "recdef" "define general recursive functions (TFL)" K.thy_decl
+ (recdef_decl >> Toplevel.theory);
+
+
+val defer_recdef_decl =
+ P.name -- Scan.repeat1 P.prop --
+ Scan.optional (P.$$$ "(" |-- P.$$$ "congs" |-- P.!!! (SpecParse.xthms1 --| P.$$$ ")")) []
+ >> (fn ((f, eqs), congs) => #1 o defer_recdef f eqs congs);
+
+val _ =
+ OuterSyntax.command "defer_recdef" "defer general recursive functions (TFL)" K.thy_decl
+ (defer_recdef_decl >> Toplevel.theory);
+
+val _ =
+ OuterSyntax.local_theory_to_proof' "recdef_tc" "recommence proof of termination condition (TFL)"
+ K.thy_goal
+ ((SpecParse.opt_thm_name ":" >> apfst Binding.name_of) -- P.xname --
+ Scan.option (P.$$$ "(" |-- P.nat --| P.$$$ ")")
+ >> (fn ((thm_name, name), i) => recdef_tc thm_name name i));
+
+end;
+
+end;
--- a/src/HOL/Tools/recdef_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-(* Title: HOL/Tools/recdef_package.ML
- Author: Markus Wenzel, TU Muenchen
-
-Wrapper module for Konrad Slind's TFL package.
-*)
-
-signature RECDEF_PACKAGE =
-sig
- val get_recdef: theory -> string
- -> {simps: thm list, rules: thm list list, induct: thm, tcs: term list} option
- val get_hints: Proof.context -> {simps: thm list, congs: (string * thm) list, wfs: thm list}
- val simp_add: attribute
- val simp_del: attribute
- val cong_add: attribute
- val cong_del: attribute
- val wf_add: attribute
- val wf_del: attribute
- val add_recdef: bool -> xstring -> string -> ((binding * string) * Attrib.src list) list ->
- Attrib.src option -> theory -> theory
- * {simps: thm list, rules: thm list list, induct: thm, tcs: term list}
- val add_recdef_i: bool -> xstring -> term -> ((binding * term) * attribute list) list ->
- theory -> theory * {simps: thm list, rules: thm list list, induct: thm, tcs: term list}
- val defer_recdef: xstring -> string list -> (Facts.ref * Attrib.src list) list
- -> theory -> theory * {induct_rules: thm}
- val defer_recdef_i: xstring -> term list -> thm list -> theory -> theory * {induct_rules: thm}
- val recdef_tc: bstring * Attrib.src list -> xstring -> int option -> bool ->
- local_theory -> Proof.state
- val recdef_tc_i: bstring * Attrib.src list -> string -> int option -> bool ->
- local_theory -> Proof.state
- val setup: theory -> theory
-end;
-
-structure RecdefPackage: RECDEF_PACKAGE =
-struct
-
-
-(** recdef hints **)
-
-(* type hints *)
-
-type hints = {simps: thm list, congs: (string * thm) list, wfs: thm list};
-
-fun mk_hints (simps, congs, wfs) = {simps = simps, congs = congs, wfs = wfs}: hints;
-fun map_hints f ({simps, congs, wfs}: hints) = mk_hints (f (simps, congs, wfs));
-
-fun map_simps f = map_hints (fn (simps, congs, wfs) => (f simps, congs, wfs));
-fun map_congs f = map_hints (fn (simps, congs, wfs) => (simps, f congs, wfs));
-fun map_wfs f = map_hints (fn (simps, congs, wfs) => (simps, congs, f wfs));
-
-fun pretty_hints ({simps, congs, wfs}: hints) =
- [Pretty.big_list "recdef simp hints:" (map Display.pretty_thm simps),
- Pretty.big_list "recdef cong hints:" (map Display.pretty_thm (map snd congs)),
- Pretty.big_list "recdef wf hints:" (map Display.pretty_thm wfs)];
-
-
-(* congruence rules *)
-
-local
-
-val cong_head =
- fst o Term.dest_Const o Term.head_of o fst o Logic.dest_equals o Thm.concl_of;
-
-fun prep_cong raw_thm =
- let val thm = safe_mk_meta_eq raw_thm in (cong_head thm, thm) end;
-
-in
-
-fun add_cong raw_thm congs =
- let
- val (c, thm) = prep_cong raw_thm;
- val _ = if AList.defined (op =) congs c
- then warning ("Overwriting recdef congruence rule for " ^ quote c)
- else ();
- in AList.update (op =) (c, thm) congs end;
-
-fun del_cong raw_thm congs =
- let
- val (c, thm) = prep_cong raw_thm;
- val _ = if AList.defined (op =) congs c
- then ()
- else warning ("No recdef congruence rule for " ^ quote c);
- in AList.delete (op =) c congs end;
-
-end;
-
-
-
-(** global and local recdef data **)
-
-(* theory data *)
-
-type recdef_info = {simps: thm list, rules: thm list list, induct: thm, tcs: term list};
-
-structure GlobalRecdefData = TheoryDataFun
-(
- type T = recdef_info Symtab.table * hints;
- val empty = (Symtab.empty, mk_hints ([], [], [])): T;
- val copy = I;
- val extend = I;
- fun merge _
- ((tab1, {simps = simps1, congs = congs1, wfs = wfs1}),
- (tab2, {simps = simps2, congs = congs2, wfs = wfs2})) : T =
- (Symtab.merge (K true) (tab1, tab2),
- mk_hints (Thm.merge_thms (simps1, simps2),
- AList.merge (op =) Thm.eq_thm (congs1, congs2),
- Thm.merge_thms (wfs1, wfs2)));
-);
-
-val get_recdef = Symtab.lookup o #1 o GlobalRecdefData.get;
-
-fun put_recdef name info thy =
- let
- val (tab, hints) = GlobalRecdefData.get thy;
- val tab' = Symtab.update_new (name, info) tab
- handle Symtab.DUP _ => error ("Duplicate recursive function definition " ^ quote name);
- in GlobalRecdefData.put (tab', hints) thy end;
-
-val get_global_hints = #2 o GlobalRecdefData.get;
-
-
-(* proof data *)
-
-structure LocalRecdefData = ProofDataFun
-(
- type T = hints;
- val init = get_global_hints;
-);
-
-val get_hints = LocalRecdefData.get;
-fun map_hints f = Context.mapping (GlobalRecdefData.map (apsnd f)) (LocalRecdefData.map f);
-
-
-(* attributes *)
-
-fun attrib f = Thm.declaration_attribute (map_hints o f);
-
-val simp_add = attrib (map_simps o Thm.add_thm);
-val simp_del = attrib (map_simps o Thm.del_thm);
-val cong_add = attrib (map_congs o add_cong);
-val cong_del = attrib (map_congs o del_cong);
-val wf_add = attrib (map_wfs o Thm.add_thm);
-val wf_del = attrib (map_wfs o Thm.del_thm);
-
-
-(* modifiers *)
-
-val recdef_simpN = "recdef_simp";
-val recdef_congN = "recdef_cong";
-val recdef_wfN = "recdef_wf";
-
-val recdef_modifiers =
- [Args.$$$ recdef_simpN -- Args.colon >> K ((I, simp_add): Method.modifier),
- Args.$$$ recdef_simpN -- Args.add -- Args.colon >> K (I, simp_add),
- Args.$$$ recdef_simpN -- Args.del -- Args.colon >> K (I, simp_del),
- Args.$$$ recdef_congN -- Args.colon >> K (I, cong_add),
- Args.$$$ recdef_congN -- Args.add -- Args.colon >> K (I, cong_add),
- Args.$$$ recdef_congN -- Args.del -- Args.colon >> K (I, cong_del),
- Args.$$$ recdef_wfN -- Args.colon >> K (I, wf_add),
- Args.$$$ recdef_wfN -- Args.add -- Args.colon >> K (I, wf_add),
- Args.$$$ recdef_wfN -- Args.del -- Args.colon >> K (I, wf_del)] @
- Clasimp.clasimp_modifiers;
-
-
-
-(** prepare_hints(_i) **)
-
-fun prepare_hints thy opt_src =
- let
- val ctxt0 = ProofContext.init thy;
- val ctxt =
- (case opt_src of
- NONE => ctxt0
- | SOME src => #2 (Method.syntax (Method.sections recdef_modifiers) src ctxt0));
- val {simps, congs, wfs} = get_hints ctxt;
- val cs = local_claset_of ctxt;
- val ss = local_simpset_of ctxt addsimps simps;
- in (cs, ss, rev (map snd congs), wfs) end;
-
-fun prepare_hints_i thy () =
- let
- val ctxt0 = ProofContext.init thy;
- val {simps, congs, wfs} = get_global_hints thy;
- in (local_claset_of ctxt0, local_simpset_of ctxt0 addsimps simps, rev (map snd congs), wfs) end;
-
-
-
-(** add_recdef(_i) **)
-
-fun requires_recdef thy = Theory.requires thy "Recdef" "recursive functions";
-
-fun gen_add_recdef tfl_fn prep_att prep_hints not_permissive raw_name R eq_srcs hints thy =
- let
- val _ = requires_recdef thy;
-
- val name = Sign.intern_const thy raw_name;
- val bname = Long_Name.base_name name;
- val _ = writeln ("Defining recursive function " ^ quote name ^ " ...");
-
- val ((eq_names, eqs), raw_eq_atts) = apfst split_list (split_list eq_srcs);
- val eq_atts = map (map (prep_att thy)) raw_eq_atts;
-
- val (cs, ss, congs, wfs) = prep_hints thy hints;
- (*We must remove imp_cong to prevent looping when the induction rule
- is simplified. Many induction rules have nested implications that would
- give rise to looping conditional rewriting.*)
- val (thy, {rules = rules_idx, induct, tcs}) =
- tfl_fn not_permissive thy cs (ss delcongs [imp_cong])
- congs wfs name R eqs;
- val rules = (map o map) fst (partition_eq (eq_snd (op = : int * int -> bool)) rules_idx);
- val simp_att = if null tcs then [Simplifier.simp_add, Nitpick_Const_Simp_Thms.add,
- Code.add_default_eqn_attribute, Quickcheck_RecFun_Simp_Thms.add] else [];
-
- val ((simps' :: rules', [induct']), thy) =
- thy
- |> Sign.add_path bname
- |> PureThy.add_thmss
- (((Binding.name "simps", List.concat rules), simp_att) :: ((eq_names ~~ rules) ~~ eq_atts))
- ||>> PureThy.add_thms [((Binding.name "induct", induct), [])];
- val result = {simps = simps', rules = rules', induct = induct', tcs = tcs};
- val thy =
- thy
- |> put_recdef name result
- |> Sign.parent_path;
- in (thy, result) end;
-
-val add_recdef = gen_add_recdef Tfl.define Attrib.attribute prepare_hints;
-fun add_recdef_i x y z w = gen_add_recdef Tfl.define_i (K I) prepare_hints_i x y z w ();
-
-
-
-(** defer_recdef(_i) **)
-
-fun gen_defer_recdef tfl_fn eval_thms raw_name eqs raw_congs thy =
- let
- val name = Sign.intern_const thy raw_name;
- val bname = Long_Name.base_name name;
-
- val _ = requires_recdef thy;
- val _ = writeln ("Deferred recursive function " ^ quote name ^ " ...");
-
- val congs = eval_thms (ProofContext.init thy) raw_congs;
- val (thy2, induct_rules) = tfl_fn thy congs name eqs;
- val ([induct_rules'], thy3) =
- thy2
- |> Sign.add_path bname
- |> PureThy.add_thms [((Binding.name "induct_rules", induct_rules), [])]
- ||> Sign.parent_path;
- in (thy3, {induct_rules = induct_rules'}) end;
-
-val defer_recdef = gen_defer_recdef Tfl.defer Attrib.eval_thms;
-val defer_recdef_i = gen_defer_recdef Tfl.defer_i (K I);
-
-
-
-(** recdef_tc(_i) **)
-
-fun gen_recdef_tc prep_att prep_name (bname, raw_atts) raw_name opt_i int lthy =
- let
- val thy = ProofContext.theory_of lthy;
- val name = prep_name thy raw_name;
- val atts = map (prep_att thy) raw_atts;
- val tcs =
- (case get_recdef thy name of
- NONE => error ("No recdef definition of constant: " ^ quote name)
- | SOME {tcs, ...} => tcs);
- val i = the_default 1 opt_i;
- val tc = nth tcs (i - 1) handle Subscript =>
- error ("No termination condition #" ^ string_of_int i ^
- " in recdef definition of " ^ quote name);
- in
- Specification.theorem Thm.internalK NONE (K I) (Binding.name bname, atts)
- [] (Element.Shows [(Attrib.empty_binding, [(HOLogic.mk_Trueprop tc, [])])]) int lthy
- end;
-
-val recdef_tc = gen_recdef_tc Attrib.intern_src Sign.intern_const;
-val recdef_tc_i = gen_recdef_tc (K I) (K I);
-
-
-
-(** package setup **)
-
-(* setup theory *)
-
-val setup =
- Attrib.setup @{binding recdef_simp} (Attrib.add_del simp_add simp_del)
- "declaration of recdef simp rule" #>
- Attrib.setup @{binding recdef_cong} (Attrib.add_del cong_add cong_del)
- "declaration of recdef cong rule" #>
- Attrib.setup @{binding recdef_wf} (Attrib.add_del wf_add wf_del)
- "declaration of recdef wf rule";
-
-
-(* outer syntax *)
-
-local structure P = OuterParse and K = OuterKeyword in
-
-val _ = List.app OuterKeyword.keyword ["permissive", "congs", "hints"];
-
-val hints =
- P.$$$ "(" |-- P.!!! (P.position (P.$$$ "hints" -- Args.parse) --| P.$$$ ")") >> Args.src;
-
-val recdef_decl =
- Scan.optional (P.$$$ "(" -- P.!!! (P.$$$ "permissive" -- P.$$$ ")") >> K false) true --
- P.name -- P.term -- Scan.repeat1 (SpecParse.opt_thm_name ":" -- P.prop)
- -- Scan.option hints
- >> (fn ((((p, f), R), eqs), src) => #1 o add_recdef p f R (map P.triple_swap eqs) src);
-
-val _ =
- OuterSyntax.command "recdef" "define general recursive functions (TFL)" K.thy_decl
- (recdef_decl >> Toplevel.theory);
-
-
-val defer_recdef_decl =
- P.name -- Scan.repeat1 P.prop --
- Scan.optional (P.$$$ "(" |-- P.$$$ "congs" |-- P.!!! (SpecParse.xthms1 --| P.$$$ ")")) []
- >> (fn ((f, eqs), congs) => #1 o defer_recdef f eqs congs);
-
-val _ =
- OuterSyntax.command "defer_recdef" "defer general recursive functions (TFL)" K.thy_decl
- (defer_recdef_decl >> Toplevel.theory);
-
-val _ =
- OuterSyntax.local_theory_to_proof' "recdef_tc" "recommence proof of termination condition (TFL)"
- K.thy_goal
- ((SpecParse.opt_thm_name ":" >> apfst Binding.name_of) -- P.xname --
- Scan.option (P.$$$ "(" |-- P.nat --| P.$$$ ")")
- >> (fn ((thm_name, name), i) => recdef_tc thm_name name i));
-
-end;
-
-end;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/record.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,2325 @@
+(* Title: HOL/Tools/record.ML
+ Author: Wolfgang Naraschewski, Norbert Schirmer and Markus Wenzel, TU Muenchen
+
+Extensible records with structural subtyping in HOL.
+*)
+
+
+signature BASIC_RECORD =
+sig
+ val record_simproc: simproc
+ val record_eq_simproc: simproc
+ val record_upd_simproc: simproc
+ val record_split_simproc: (term -> int) -> simproc
+ val record_ex_sel_eq_simproc: simproc
+ val record_split_tac: int -> tactic
+ val record_split_simp_tac: thm list -> (term -> int) -> int -> tactic
+ val record_split_name: string
+ val record_split_wrapper: string * wrapper
+ val print_record_type_abbr: bool ref
+ val print_record_type_as_fields: bool ref
+end;
+
+signature RECORD =
+sig
+ include BASIC_RECORD
+ val timing: bool ref
+ val record_quick_and_dirty_sensitive: bool ref
+ val updateN: string
+ val updN: string
+ val ext_typeN: string
+ val extN: string
+ val makeN: string
+ val moreN: string
+ val ext_dest: string
+
+ val last_extT: typ -> (string * typ list) option
+ val dest_recTs : typ -> (string * typ list) list
+ val get_extT_fields: theory -> typ -> (string * typ) list * (string * typ)
+ val get_recT_fields: theory -> typ -> (string * typ) list * (string * typ)
+ val get_parent: theory -> string -> (typ list * string) option
+ val get_extension: theory -> string -> (string * typ list) option
+ val get_extinjects: theory -> thm list
+ val get_simpset: theory -> simpset
+ val print_records: theory -> unit
+ val read_typ: Proof.context -> string -> (string * sort) list -> typ * (string * sort) list
+ val cert_typ: Proof.context -> typ -> (string * sort) list -> typ * (string * sort) list
+ val add_record: bool -> string list * string -> string option -> (string * string * mixfix) list
+ -> theory -> theory
+ val add_record_i: bool -> string list * string -> (typ list * string) option
+ -> (string * typ * mixfix) list -> theory -> theory
+ val setup: theory -> theory
+end;
+
+
+structure Record: RECORD =
+struct
+
+val eq_reflection = thm "eq_reflection";
+val rec_UNIV_I = thm "rec_UNIV_I";
+val rec_True_simp = thm "rec_True_simp";
+val Pair_eq = thm "Product_Type.prod.inject";
+val atomize_all = thm "HOL.atomize_all";
+val atomize_imp = thm "HOL.atomize_imp";
+val meta_allE = thm "Pure.meta_allE";
+val prop_subst = thm "prop_subst";
+val Pair_sel_convs = [fst_conv,snd_conv];
+val K_record_comp = @{thm "K_record_comp"};
+val K_comp_convs = [@{thm o_apply}, K_record_comp]
+
+(** name components **)
+
+val rN = "r";
+val wN = "w";
+val moreN = "more";
+val schemeN = "_scheme";
+val ext_typeN = "_ext_type";
+val extN ="_ext";
+val casesN = "_cases";
+val ext_dest = "_sel";
+val updateN = "_update";
+val updN = "_upd";
+val makeN = "make";
+val fields_selN = "fields";
+val extendN = "extend";
+val truncateN = "truncate";
+
+(*see typedef.ML*)
+val RepN = "Rep_";
+val AbsN = "Abs_";
+
+(*** utilities ***)
+
+fun but_last xs = fst (split_last xs);
+
+fun varifyT midx =
+ let fun varify (a, S) = TVar ((a, midx + 1), S);
+ in map_type_tfree varify end;
+
+fun domain_type' T =
+ domain_type T handle Match => T;
+
+fun range_type' T =
+ range_type T handle Match => T;
+
+(* messages *)
+
+fun trace_thm str thm =
+ tracing (str ^ (Pretty.string_of (Display.pretty_thm thm)));
+
+fun trace_thms str thms =
+ (tracing str; map (trace_thm "") thms);
+
+fun trace_term str t =
+ tracing (str ^ Syntax.string_of_term_global Pure.thy t);
+
+(* timing *)
+
+val timing = ref false;
+fun timeit_msg s x = if !timing then (warning s; timeit x) else x ();
+fun timing_msg s = if !timing then warning s else ();
+
+(* syntax *)
+
+fun prune n xs = Library.drop (n, xs);
+fun prefix_base s = Long_Name.map_base_name (fn bname => s ^ bname);
+
+val Trueprop = HOLogic.mk_Trueprop;
+fun All xs t = Term.list_all_free (xs, t);
+
+infix 9 $$;
+infix 0 :== ===;
+infixr 0 ==>;
+
+val (op $$) = Term.list_comb;
+val (op :==) = PrimitiveDefs.mk_defpair;
+val (op ===) = Trueprop o HOLogic.mk_eq;
+val (op ==>) = Logic.mk_implies;
+
+(* morphisms *)
+
+fun mk_RepN name = suffix ext_typeN (prefix_base RepN name);
+fun mk_AbsN name = suffix ext_typeN (prefix_base AbsN name);
+
+fun mk_Rep name repT absT =
+ Const (suffix ext_typeN (prefix_base RepN name),absT --> repT);
+
+fun mk_Abs name repT absT =
+ Const (mk_AbsN name,repT --> absT);
+
+(* constructor *)
+
+fun mk_extC (name,T) Ts = (suffix extN name, Ts ---> T);
+
+fun mk_ext (name,T) ts =
+ let val Ts = map fastype_of ts
+ in list_comb (Const (mk_extC (name,T) Ts),ts) end;
+
+(* cases *)
+
+fun mk_casesC (name,T,vT) Ts = (suffix casesN name, (Ts ---> vT) --> T --> vT)
+
+fun mk_cases (name,T,vT) f =
+ let val Ts = binder_types (fastype_of f)
+ in Const (mk_casesC (name,T,vT) Ts) $ f end;
+
+(* selector *)
+
+fun mk_selC sT (c,T) = (c,sT --> T);
+
+fun mk_sel s (c,T) =
+ let val sT = fastype_of s
+ in Const (mk_selC sT (c,T)) $ s end;
+
+(* updates *)
+
+fun mk_updC sfx sT (c,T) = (suffix sfx c, (T --> T) --> sT --> sT);
+
+fun mk_upd' sfx c v sT =
+ let val vT = domain_type (fastype_of v);
+ in Const (mk_updC sfx sT (c, vT)) $ v end;
+
+fun mk_upd sfx c v s = mk_upd' sfx c v (fastype_of s) $ s
+
+(* types *)
+
+fun dest_recT (typ as Type (c_ext_type, Ts as (T::_))) =
+ (case try (unsuffix ext_typeN) c_ext_type of
+ NONE => raise TYPE ("Record.dest_recT", [typ], [])
+ | SOME c => ((c, Ts), List.last Ts))
+ | dest_recT typ = raise TYPE ("Record.dest_recT", [typ], []);
+
+fun is_recT T =
+ (case try dest_recT T of NONE => false | SOME _ => true);
+
+fun dest_recTs T =
+ let val ((c, Ts), U) = dest_recT T
+ in (c, Ts) :: dest_recTs U
+ end handle TYPE _ => [];
+
+fun last_extT T =
+ let val ((c, Ts), U) = dest_recT T
+ in (case last_extT U of
+ NONE => SOME (c,Ts)
+ | SOME l => SOME l)
+ end handle TYPE _ => NONE
+
+fun rec_id i T =
+ let val rTs = dest_recTs T
+ val rTs' = if i < 0 then rTs else Library.take (i,rTs)
+ in Library.foldl (fn (s,(c,T)) => s ^ c) ("",rTs') end;
+
+(*** extend theory by record definition ***)
+
+(** record info **)
+
+(* type record_info and parent_info *)
+
+type record_info =
+ {args: (string * sort) list,
+ parent: (typ list * string) option,
+ fields: (string * typ) list,
+ extension: (string * typ list),
+ induct: thm
+ };
+
+fun make_record_info args parent fields extension induct =
+ {args = args, parent = parent, fields = fields, extension = extension,
+ induct = induct}: record_info;
+
+
+type parent_info =
+ {name: string,
+ fields: (string * typ) list,
+ extension: (string * typ list),
+ induct: thm
+};
+
+fun make_parent_info name fields extension induct =
+ {name = name, fields = fields, extension = extension, induct = induct}: parent_info;
+
+
+(* theory data *)
+
+type record_data =
+ {records: record_info Symtab.table,
+ sel_upd:
+ {selectors: unit Symtab.table,
+ updates: string Symtab.table,
+ simpset: Simplifier.simpset},
+ equalities: thm Symtab.table,
+ extinjects: thm list,
+ extsplit: thm Symtab.table, (* maps extension name to split rule *)
+ splits: (thm*thm*thm*thm) Symtab.table, (* !!,!,EX - split-equalities,induct rule *)
+ extfields: (string*typ) list Symtab.table, (* maps extension to its fields *)
+ fieldext: (string*typ list) Symtab.table (* maps field to its extension *)
+};
+
+fun make_record_data
+ records sel_upd equalities extinjects extsplit splits extfields fieldext =
+ {records = records, sel_upd = sel_upd,
+ equalities = equalities, extinjects=extinjects, extsplit = extsplit, splits = splits,
+ extfields = extfields, fieldext = fieldext }: record_data;
+
+structure RecordsData = TheoryDataFun
+(
+ type T = record_data;
+ val empty =
+ make_record_data Symtab.empty
+ {selectors = Symtab.empty, updates = Symtab.empty, simpset = HOL_basic_ss}
+ Symtab.empty [] Symtab.empty Symtab.empty Symtab.empty Symtab.empty;
+
+ val copy = I;
+ val extend = I;
+ fun merge _
+ ({records = recs1,
+ sel_upd = {selectors = sels1, updates = upds1, simpset = ss1},
+ equalities = equalities1,
+ extinjects = extinjects1,
+ extsplit = extsplit1,
+ splits = splits1,
+ extfields = extfields1,
+ fieldext = fieldext1},
+ {records = recs2,
+ sel_upd = {selectors = sels2, updates = upds2, simpset = ss2},
+ equalities = equalities2,
+ extinjects = extinjects2,
+ extsplit = extsplit2,
+ splits = splits2,
+ extfields = extfields2,
+ fieldext = fieldext2}) =
+ make_record_data
+ (Symtab.merge (K true) (recs1, recs2))
+ {selectors = Symtab.merge (K true) (sels1, sels2),
+ updates = Symtab.merge (K true) (upds1, upds2),
+ simpset = Simplifier.merge_ss (ss1, ss2)}
+ (Symtab.merge Thm.eq_thm_prop (equalities1, equalities2))
+ (Library.merge Thm.eq_thm_prop (extinjects1, extinjects2))
+ (Symtab.merge Thm.eq_thm_prop (extsplit1,extsplit2))
+ (Symtab.merge (fn ((a,b,c,d),(w,x,y,z))
+ => Thm.eq_thm (a,w) andalso Thm.eq_thm (b,x) andalso
+ Thm.eq_thm (c,y) andalso Thm.eq_thm (d,z))
+ (splits1, splits2))
+ (Symtab.merge (K true) (extfields1,extfields2))
+ (Symtab.merge (K true) (fieldext1,fieldext2));
+);
+
+fun print_records thy =
+ let
+ val {records = recs, ...} = RecordsData.get thy;
+ val prt_typ = Syntax.pretty_typ_global thy;
+
+ fun pretty_parent NONE = []
+ | pretty_parent (SOME (Ts, name)) =
+ [Pretty.block [prt_typ (Type (name, Ts)), Pretty.str " +"]];
+
+ fun pretty_field (c, T) = Pretty.block
+ [Pretty.str (Sign.extern_const thy c), Pretty.str " ::",
+ Pretty.brk 1, Pretty.quote (prt_typ T)];
+
+ fun pretty_record (name, {args, parent, fields, ...}: record_info) =
+ Pretty.block (Pretty.fbreaks (Pretty.block
+ [prt_typ (Type (name, map TFree args)), Pretty.str " = "] ::
+ pretty_parent parent @ map pretty_field fields));
+ in map pretty_record (Symtab.dest recs) |> Pretty.chunks |> Pretty.writeln end;
+
+
+(* access 'records' *)
+
+val get_record = Symtab.lookup o #records o RecordsData.get;
+
+fun put_record name info thy =
+ let
+ val {records, sel_upd, equalities, extinjects,extsplit,splits,extfields,fieldext} =
+ RecordsData.get thy;
+ val data = make_record_data (Symtab.update (name, info) records)
+ sel_upd equalities extinjects extsplit splits extfields fieldext;
+ in RecordsData.put data thy end;
+
+
+(* access 'sel_upd' *)
+
+val get_sel_upd = #sel_upd o RecordsData.get;
+
+val is_selector = Symtab.defined o #selectors o get_sel_upd;
+val get_updates = Symtab.lookup o #updates o get_sel_upd;
+fun get_simpset thy = Simplifier.theory_context thy (#simpset (get_sel_upd thy));
+
+fun put_sel_upd names simps = RecordsData.map (fn {records,
+ sel_upd = {selectors, updates, simpset},
+ equalities, extinjects, extsplit, splits, extfields, fieldext} =>
+ make_record_data records
+ {selectors = fold (fn name => Symtab.update (name, ())) names selectors,
+ updates = fold (fn name => Symtab.update ((suffix updateN) name, name)) names updates,
+ simpset = Simplifier.addsimps (simpset, simps)}
+ equalities extinjects extsplit splits extfields fieldext);
+
+
+(* access 'equalities' *)
+
+fun add_record_equalities name thm thy =
+ let
+ val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields,fieldext} =
+ RecordsData.get thy;
+ val data = make_record_data records sel_upd
+ (Symtab.update_new (name, thm) equalities) extinjects extsplit
+ splits extfields fieldext;
+ in RecordsData.put data thy end;
+
+val get_equalities =Symtab.lookup o #equalities o RecordsData.get;
+
+
+(* access 'extinjects' *)
+
+fun add_extinjects thm thy =
+ let
+ val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields,fieldext} =
+ RecordsData.get thy;
+ val data =
+ make_record_data records sel_upd equalities (insert Thm.eq_thm_prop thm extinjects) extsplit
+ splits extfields fieldext;
+ in RecordsData.put data thy end;
+
+val get_extinjects = rev o #extinjects o RecordsData.get;
+
+
+(* access 'extsplit' *)
+
+fun add_extsplit name thm thy =
+ let
+ val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields,fieldext} =
+ RecordsData.get thy;
+ val data = make_record_data records sel_upd
+ equalities extinjects (Symtab.update_new (name, thm) extsplit) splits
+ extfields fieldext;
+ in RecordsData.put data thy end;
+
+val get_extsplit = Symtab.lookup o #extsplit o RecordsData.get;
+
+
+(* access 'splits' *)
+
+fun add_record_splits name thmP thy =
+ let
+ val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields,fieldext} =
+ RecordsData.get thy;
+ val data = make_record_data records sel_upd
+ equalities extinjects extsplit (Symtab.update_new (name, thmP) splits)
+ extfields fieldext;
+ in RecordsData.put data thy end;
+
+val get_splits = Symtab.lookup o #splits o RecordsData.get;
+
+
+(* parent/extension of named record *)
+
+val get_parent = (Option.join o Option.map #parent) oo (Symtab.lookup o #records o RecordsData.get);
+val get_extension = Option.map #extension oo (Symtab.lookup o #records o RecordsData.get);
+
+
+(* access 'extfields' *)
+
+fun add_extfields name fields thy =
+ let
+ val {records, sel_upd, equalities, extinjects, extsplit,splits, extfields, fieldext} =
+ RecordsData.get thy;
+ val data = make_record_data records sel_upd
+ equalities extinjects extsplit splits
+ (Symtab.update_new (name, fields) extfields) fieldext;
+ in RecordsData.put data thy end;
+
+val get_extfields = Symtab.lookup o #extfields o RecordsData.get;
+
+fun get_extT_fields thy T =
+ let
+ val ((name,Ts),moreT) = dest_recT T;
+ val recname = let val (nm::recn::rst) = rev (Long_Name.explode name)
+ in Long_Name.implode (rev (nm::rst)) end;
+ val midx = maxidx_of_typs (moreT::Ts);
+ val varifyT = varifyT midx;
+ val {records,extfields,...} = RecordsData.get thy;
+ val (flds,(more,_)) = split_last (Symtab.lookup_list extfields name);
+ val args = map varifyT (snd (#extension (the (Symtab.lookup records recname))));
+
+ val subst = fold (Sign.typ_match thy) (but_last args ~~ but_last Ts) (Vartab.empty);
+ val flds' = map (apsnd ((Envir.norm_type subst) o varifyT)) flds;
+ in (flds',(more,moreT)) end;
+
+fun get_recT_fields thy T =
+ let
+ val (root_flds,(root_more,root_moreT)) = get_extT_fields thy T;
+ val (rest_flds,rest_more) =
+ if is_recT root_moreT then get_recT_fields thy root_moreT
+ else ([],(root_more,root_moreT));
+ in (root_flds@rest_flds,rest_more) end;
+
+
+(* access 'fieldext' *)
+
+fun add_fieldext extname_types fields thy =
+ let
+ val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields, fieldext} =
+ RecordsData.get thy;
+ val fieldext' =
+ fold (fn field => Symtab.update_new (field, extname_types)) fields fieldext;
+ val data=make_record_data records sel_upd equalities extinjects extsplit
+ splits extfields fieldext';
+ in RecordsData.put data thy end;
+
+
+val get_fieldext = Symtab.lookup o #fieldext o RecordsData.get;
+
+
+(* parent records *)
+
+fun add_parents thy NONE parents = parents
+ | add_parents thy (SOME (types, name)) parents =
+ let
+ fun err msg = error (msg ^ " parent record " ^ quote name);
+
+ val {args, parent, fields, extension, induct} =
+ (case get_record thy name of SOME info => info | NONE => err "Unknown");
+ val _ = if length types <> length args then err "Bad number of arguments for" else ();
+
+ fun bad_inst ((x, S), T) =
+ if Sign.of_sort thy (T, S) then NONE else SOME x
+ val bads = List.mapPartial bad_inst (args ~~ types);
+ val _ = null bads orelse err ("Ill-sorted instantiation of " ^ commas bads ^ " in");
+
+ val inst = map fst args ~~ types;
+ val subst = Term.map_type_tfree (the o AList.lookup (op =) inst o fst);
+ val parent' = Option.map (apfst (map subst)) parent;
+ val fields' = map (apsnd subst) fields;
+ val extension' = apsnd (map subst) extension;
+ in
+ add_parents thy parent'
+ (make_parent_info name fields' extension' induct :: parents)
+ end;
+
+
+
+(** concrete syntax for records **)
+
+(* decode type *)
+
+fun decode_type thy t =
+ let
+ fun get_sort xs n = AList.lookup (op =) xs (n: indexname) |> the_default (Sign.defaultS thy);
+ val map_sort = Sign.intern_sort thy;
+ in
+ Syntax.typ_of_term (get_sort (Syntax.term_sorts map_sort t)) map_sort t
+ |> Sign.intern_tycons thy
+ end;
+
+
+(* parse translations *)
+
+fun gen_field_tr mark sfx (t as Const (c, _) $ Const (name, _) $ arg) =
+ if c = mark then Syntax.const (suffix sfx name) $ (Abs ("_",dummyT, arg))
+ else raise TERM ("gen_field_tr: " ^ mark, [t])
+ | gen_field_tr mark _ t = raise TERM ("gen_field_tr: " ^ mark, [t]);
+
+fun gen_fields_tr sep mark sfx (tm as Const (c, _) $ t $ u) =
+ if c = sep then gen_field_tr mark sfx t :: gen_fields_tr sep mark sfx u
+ else [gen_field_tr mark sfx tm]
+ | gen_fields_tr _ mark sfx tm = [gen_field_tr mark sfx tm];
+
+
+fun record_update_tr [t, u] =
+ Library.foldr (op $) (rev (gen_fields_tr "_updates" "_update" updateN u), t)
+ | record_update_tr ts = raise TERM ("record_update_tr", ts);
+
+fun update_name_tr (Free (x, T) :: ts) = Free (suffix updateN x, T) $$ ts
+ | update_name_tr (Const (x, T) :: ts) = Const (suffix updateN x, T) $$ ts
+ | update_name_tr (((c as Const ("_constrain", _)) $ t $ ty) :: ts) =
+ (c $ update_name_tr [t] $ (Syntax.const "fun" $ ty $ Syntax.const "dummy")) $$ ts
+ | update_name_tr ts = raise TERM ("update_name_tr", ts);
+
+fun dest_ext_field mark (t as (Const (c,_) $ Const (name,_) $ arg)) =
+ if c = mark then (name,arg) else raise TERM ("dest_ext_field: " ^ mark, [t])
+ | dest_ext_field _ t = raise TERM ("dest_ext_field", [t])
+
+fun dest_ext_fields sep mark (trm as (Const (c,_) $ t $ u)) =
+ if c = sep then dest_ext_field mark t::dest_ext_fields sep mark u
+ else [dest_ext_field mark trm]
+ | dest_ext_fields _ mark t = [dest_ext_field mark t]
+
+fun gen_ext_fields_tr sep mark sfx more ctxt t =
+ let
+ val thy = ProofContext.theory_of ctxt;
+ val msg = "error in record input: ";
+ val fieldargs = dest_ext_fields sep mark t;
+ fun splitargs (field::fields) ((name,arg)::fargs) =
+ if can (unsuffix name) field
+ then let val (args,rest) = splitargs fields fargs
+ in (arg::args,rest) end
+ else raise TERM (msg ^ "expecting field " ^ field ^ " but got " ^ name, [t])
+ | splitargs [] (fargs as (_::_)) = ([],fargs)
+ | splitargs (_::_) [] = raise TERM (msg ^ "expecting more fields", [t])
+ | splitargs _ _ = ([],[]);
+
+ fun mk_ext (fargs as (name,arg)::_) =
+ (case get_fieldext thy (Sign.intern_const thy name) of
+ SOME (ext,_) => (case get_extfields thy ext of
+ SOME flds
+ => let val (args,rest) =
+ splitargs (map fst (but_last flds)) fargs;
+ val more' = mk_ext rest;
+ in list_comb (Syntax.const (suffix sfx ext),args@[more'])
+ end
+ | NONE => raise TERM(msg ^ "no fields defined for "
+ ^ ext,[t]))
+ | NONE => raise TERM (msg ^ name ^" is no proper field",[t]))
+ | mk_ext [] = more
+
+ in mk_ext fieldargs end;
+
+fun gen_ext_type_tr sep mark sfx more ctxt t =
+ let
+ val thy = ProofContext.theory_of ctxt;
+ val msg = "error in record-type input: ";
+ val fieldargs = dest_ext_fields sep mark t;
+ fun splitargs (field::fields) ((name,arg)::fargs) =
+ if can (unsuffix name) field
+ then let val (args,rest) = splitargs fields fargs
+ in (arg::args,rest) end
+ else raise TERM (msg ^ "expecting field " ^ field ^ " but got " ^ name, [t])
+ | splitargs [] (fargs as (_::_)) = ([],fargs)
+ | splitargs (_::_) [] = raise TERM (msg ^ "expecting more fields", [t])
+ | splitargs _ _ = ([],[]);
+
+ fun mk_ext (fargs as (name,arg)::_) =
+ (case get_fieldext thy (Sign.intern_const thy name) of
+ SOME (ext,alphas) =>
+ (case get_extfields thy ext of
+ SOME flds
+ => (let
+ val flds' = but_last flds;
+ val types = map snd flds';
+ val (args,rest) = splitargs (map fst flds') fargs;
+ val argtypes = map (Sign.certify_typ thy o decode_type thy) args;
+ val midx = fold (fn T => fn i => Int.max (maxidx_of_typ T, i))
+ argtypes 0;
+ val varifyT = varifyT midx;
+ val vartypes = map varifyT types;
+
+ val subst = fold (Sign.typ_match thy) (vartypes ~~ argtypes)
+ Vartab.empty;
+ val alphas' = map ((Syntax.term_of_typ (! Syntax.show_sorts)) o
+ Envir.norm_type subst o varifyT)
+ (but_last alphas);
+
+ val more' = mk_ext rest;
+ in list_comb (Syntax.const (suffix sfx ext),alphas'@[more'])
+ end handle TYPE_MATCH => raise
+ TERM (msg ^ "type is no proper record (extension)", [t]))
+ | NONE => raise TERM (msg ^ "no fields defined for " ^ ext,[t]))
+ | NONE => raise TERM (msg ^ name ^" is no proper field",[t]))
+ | mk_ext [] = more
+
+ in mk_ext fieldargs end;
+
+fun gen_adv_record_tr sep mark sfx unit ctxt [t] =
+ gen_ext_fields_tr sep mark sfx unit ctxt t
+ | gen_adv_record_tr _ _ _ _ _ ts = raise TERM ("gen_record_tr", ts);
+
+fun gen_adv_record_scheme_tr sep mark sfx ctxt [t, more] =
+ gen_ext_fields_tr sep mark sfx more ctxt t
+ | gen_adv_record_scheme_tr _ _ _ _ ts = raise TERM ("gen_record_scheme_tr", ts);
+
+fun gen_adv_record_type_tr sep mark sfx unit ctxt [t] =
+ gen_ext_type_tr sep mark sfx unit ctxt t
+ | gen_adv_record_type_tr _ _ _ _ _ ts = raise TERM ("gen_record_tr", ts);
+
+fun gen_adv_record_type_scheme_tr sep mark sfx ctxt [t, more] =
+ gen_ext_type_tr sep mark sfx more ctxt t
+ | gen_adv_record_type_scheme_tr _ _ _ _ ts = raise TERM ("gen_record_scheme_tr", ts);
+
+val adv_record_tr = gen_adv_record_tr "_fields" "_field" extN HOLogic.unit;
+val adv_record_scheme_tr = gen_adv_record_scheme_tr "_fields" "_field" extN;
+
+val adv_record_type_tr =
+ gen_adv_record_type_tr "_field_types" "_field_type" ext_typeN
+ (Syntax.term_of_typ false (HOLogic.unitT));
+val adv_record_type_scheme_tr =
+ gen_adv_record_type_scheme_tr "_field_types" "_field_type" ext_typeN;
+
+
+val parse_translation =
+ [("_record_update", record_update_tr),
+ ("_update_name", update_name_tr)];
+
+
+val adv_parse_translation =
+ [("_record",adv_record_tr),
+ ("_record_scheme",adv_record_scheme_tr),
+ ("_record_type",adv_record_type_tr),
+ ("_record_type_scheme",adv_record_type_scheme_tr)];
+
+
+(* print translations *)
+
+val print_record_type_abbr = ref true;
+val print_record_type_as_fields = ref true;
+
+fun gen_field_upds_tr' mark sfx (tm as Const (name_field, _) $ k $ u) =
+ let val t = (case k of (Abs (_,_,(Abs (_,_,t)$Bound 0)))
+ => if null (loose_bnos t) then t else raise Match
+ | Abs (x,_,t) => if null (loose_bnos t) then t else raise Match
+ | _ => raise Match)
+
+ (* (case k of (Const ("K_record",_)$t) => t
+ | Abs (x,_,Const ("K_record",_)$t$Bound 0) => t
+ | _ => raise Match)*)
+ in
+ (case try (unsuffix sfx) name_field of
+ SOME name =>
+ apfst (cons (Syntax.const mark $ Syntax.free name $ t)) (gen_field_upds_tr' mark sfx u)
+ | NONE => ([], tm))
+ end
+ | gen_field_upds_tr' _ _ tm = ([], tm);
+
+fun record_update_tr' tm =
+ let val (ts, u) = gen_field_upds_tr' "_update" updateN tm in
+ if null ts then raise Match
+ else Syntax.const "_record_update" $ u $
+ foldr1 (fn (v, w) => Syntax.const "_updates" $ v $ w) (rev ts)
+ end;
+
+fun gen_field_tr' sfx tr' name =
+ let val name_sfx = suffix sfx name
+ in (name_sfx, fn [t, u] => tr' (Syntax.const name_sfx $ t $ u) | _ => raise Match) end;
+
+fun record_tr' sep mark record record_scheme unit ctxt t =
+ let
+ val thy = ProofContext.theory_of ctxt;
+ fun field_lst t =
+ (case strip_comb t of
+ (Const (ext,_),args as (_::_))
+ => (case try (unsuffix extN) (Sign.intern_const thy ext) of
+ SOME ext'
+ => (case get_extfields thy ext' of
+ SOME flds
+ => (let
+ val (f::fs) = but_last (map fst flds);
+ val flds' = Sign.extern_const thy f :: map Long_Name.base_name fs;
+ val (args',more) = split_last args;
+ in (flds'~~args')@field_lst more end
+ handle Library.UnequalLengths => [("",t)])
+ | NONE => [("",t)])
+ | NONE => [("",t)])
+ | _ => [("",t)])
+
+ val (flds,(_,more)) = split_last (field_lst t);
+ val _ = if null flds then raise Match else ();
+ val flds' = map (fn (n,t)=>Syntax.const mark$Syntax.const n$t) flds;
+ val flds'' = foldr1 (fn (x,y) => Syntax.const sep$x$y) flds';
+
+ in if unit more
+ then Syntax.const record$flds''
+ else Syntax.const record_scheme$flds''$more
+ end
+
+fun gen_record_tr' name =
+ let val name_sfx = suffix extN name;
+ val unit = (fn Const (@{const_syntax "Product_Type.Unity"},_) => true | _ => false);
+ fun tr' ctxt ts = record_tr' "_fields" "_field" "_record" "_record_scheme" unit ctxt
+ (list_comb (Syntax.const name_sfx,ts))
+ in (name_sfx,tr')
+ end
+
+fun print_translation names =
+ map (gen_field_tr' updateN record_update_tr') names;
+
+
+(* record_type_abbr_tr' tries to reconstruct the record name type abbreviation from *)
+(* the (nested) extension types. *)
+fun record_type_abbr_tr' default_tr' abbr alphas zeta lastExt schemeT ctxt tm =
+ let
+ val thy = ProofContext.theory_of ctxt;
+ (* tm is term representation of a (nested) field type. We first reconstruct the *)
+ (* type from tm so that we can continue on the type level rather then the term level.*)
+
+ (* WORKAROUND:
+ * If a record type occurs in an error message of type inference there
+ * may be some internal frees donoted by ??:
+ * (Const "_tfree",_)$Free ("??'a",_).
+
+ * This will unfortunately be translated to Type ("??'a",[]) instead of
+ * TFree ("??'a",_) by typ_of_term, which will confuse unify below.
+ * fixT works around.
+ *)
+ fun fixT (T as Type (x,[])) =
+ if String.isPrefix "??'" x then TFree (x,Sign.defaultS thy) else T
+ | fixT (Type (x,xs)) = Type (x,map fixT xs)
+ | fixT T = T;
+
+ val T = fixT (decode_type thy tm);
+ val midx = maxidx_of_typ T;
+ val varifyT = varifyT midx;
+
+ fun mk_type_abbr subst name alphas =
+ let val abbrT = Type (name, map (fn a => varifyT (TFree (a, Sign.defaultS thy))) alphas);
+ in Syntax.term_of_typ (! Syntax.show_sorts)
+ (Sign.extern_typ thy (Envir.norm_type subst abbrT)) end;
+
+ fun match rT T = (Sign.typ_match thy (varifyT rT,T)
+ Vartab.empty);
+
+ in if !print_record_type_abbr
+ then (case last_extT T of
+ SOME (name,_)
+ => if name = lastExt
+ then
+ (let
+ val subst = match schemeT T
+ in
+ if HOLogic.is_unitT (Envir.norm_type subst (varifyT (TFree(zeta,Sign.defaultS thy))))
+ then mk_type_abbr subst abbr alphas
+ else mk_type_abbr subst (suffix schemeN abbr) (alphas@[zeta])
+ end handle TYPE_MATCH => default_tr' ctxt tm)
+ else raise Match (* give print translation of specialised record a chance *)
+ | _ => raise Match)
+ else default_tr' ctxt tm
+ end
+
+fun record_type_tr' sep mark record record_scheme ctxt t =
+ let
+ val thy = ProofContext.theory_of ctxt;
+
+ val T = decode_type thy t;
+ val varifyT = varifyT (Term.maxidx_of_typ T);
+
+ fun term_of_type T = Syntax.term_of_typ (!Syntax.show_sorts) (Sign.extern_typ thy T);
+
+ fun field_lst T =
+ (case T of
+ Type (ext, args)
+ => (case try (unsuffix ext_typeN) ext of
+ SOME ext'
+ => (case get_extfields thy ext' of
+ SOME flds
+ => (case get_fieldext thy (fst (hd flds)) of
+ SOME (_, alphas)
+ => (let
+ val (f :: fs) = but_last flds;
+ val flds' = apfst (Sign.extern_const thy) f
+ :: map (apfst Long_Name.base_name) fs;
+ val (args', more) = split_last args;
+ val alphavars = map varifyT (but_last alphas);
+ val subst = fold2 (curry (Sign.typ_match thy))
+ alphavars args' Vartab.empty;
+ val flds'' = (map o apsnd)
+ (Envir.norm_type subst o varifyT) flds';
+ in flds'' @ field_lst more end
+ handle TYPE_MATCH => [("", T)]
+ | Library.UnequalLengths => [("", T)])
+ | NONE => [("", T)])
+ | NONE => [("", T)])
+ | NONE => [("", T)])
+ | _ => [("", T)])
+
+ val (flds, (_, moreT)) = split_last (field_lst T);
+ val flds' = map (fn (n, T) => Syntax.const mark $ Syntax.const n $ term_of_type T) flds;
+ val flds'' = foldr1 (fn (x, y) => Syntax.const sep $ x $ y) flds' handle Empty => raise Match;
+
+ in if not (!print_record_type_as_fields) orelse null flds then raise Match
+ else if moreT = HOLogic.unitT
+ then Syntax.const record$flds''
+ else Syntax.const record_scheme$flds''$term_of_type moreT
+ end
+
+
+fun gen_record_type_tr' name =
+ let val name_sfx = suffix ext_typeN name;
+ fun tr' ctxt ts = record_type_tr' "_field_types" "_field_type"
+ "_record_type" "_record_type_scheme" ctxt
+ (list_comb (Syntax.const name_sfx,ts))
+ in (name_sfx,tr')
+ end
+
+
+fun gen_record_type_abbr_tr' abbr alphas zeta lastExt schemeT name =
+ let val name_sfx = suffix ext_typeN name;
+ val default_tr' = record_type_tr' "_field_types" "_field_type"
+ "_record_type" "_record_type_scheme"
+ fun tr' ctxt ts =
+ record_type_abbr_tr' default_tr' abbr alphas zeta lastExt schemeT ctxt
+ (list_comb (Syntax.const name_sfx,ts))
+ in (name_sfx, tr') end;
+
+(** record simprocs **)
+
+val record_quick_and_dirty_sensitive = ref false;
+
+
+fun quick_and_dirty_prove stndrd thy asms prop tac =
+ if !record_quick_and_dirty_sensitive andalso !quick_and_dirty
+ then Goal.prove (ProofContext.init thy) [] []
+ (Logic.list_implies (map Logic.varify asms,Logic.varify prop))
+ (K (SkipProof.cheat_tac @{theory HOL}))
+ (* standard can take quite a while for large records, thats why
+ * we varify the proposition manually here.*)
+ else let val prf = Goal.prove (ProofContext.init thy) [] asms prop tac;
+ in if stndrd then standard prf else prf end;
+
+fun quick_and_dirty_prf noopt opt () =
+ if !record_quick_and_dirty_sensitive andalso !quick_and_dirty
+ then noopt ()
+ else opt ();
+
+local
+fun abstract_over_fun_app (Abs (f,fT,t)) =
+ let
+ val (f',t') = Term.dest_abs (f,fT,t);
+ val T = domain_type fT;
+ val (x,T') = hd (Term.variant_frees t' [("x",T)]);
+ val f_x = Free (f',fT)$(Free (x,T'));
+ fun is_constr (Const (c,_)$_) = can (unsuffix extN) c
+ | is_constr _ = false;
+ fun subst (t as u$w) = if Free (f',fT)=u
+ then if is_constr w then f_x
+ else raise TERM ("abstract_over_fun_app",[t])
+ else subst u$subst w
+ | subst (Abs (x,T,t)) = (Abs (x,T,subst t))
+ | subst t = t
+ val t'' = abstract_over (f_x,subst t');
+ val vars = strip_qnt_vars "all" t'';
+ val bdy = strip_qnt_body "all" t'';
+
+ in list_abs ((x,T')::vars,bdy) end
+ | abstract_over_fun_app t = raise TERM ("abstract_over_fun_app",[t]);
+(* Generates a theorem of the kind:
+ * !!f x*. PROP P (f ( r x* ) x* == !!r x*. PROP P r x*
+ *)
+fun mk_fun_apply_eq (Abs (f, fT, t)) thy =
+ let
+ val rT = domain_type fT;
+ val vars = Term.strip_qnt_vars "all" t;
+ val Ts = map snd vars;
+ val n = length vars;
+ fun app_bounds 0 t = t$Bound 0
+ | app_bounds n t = if n > 0 then app_bounds (n-1) (t$Bound n) else t
+
+
+ val [P,r] = Term.variant_frees t [("P",rT::Ts--->Term.propT),("r",Ts--->rT)];
+ val prop = Logic.mk_equals
+ (list_all ((f,fT)::vars,
+ app_bounds (n - 1) ((Free P)$(Bound n$app_bounds (n-1) (Free r)))),
+ list_all ((fst r,rT)::vars,
+ app_bounds (n - 1) ((Free P)$Bound n)));
+ val prove_standard = quick_and_dirty_prove true thy;
+ val thm = prove_standard [] prop (fn _ =>
+ EVERY [rtac equal_intr_rule 1,
+ Goal.norm_hhf_tac 1,REPEAT (etac meta_allE 1), atac 1,
+ Goal.norm_hhf_tac 1,REPEAT (etac meta_allE 1), atac 1]);
+ in thm end
+ | mk_fun_apply_eq t thy = raise TERM ("mk_fun_apply_eq",[t]);
+
+in
+(* During proof of theorems produced by record_simproc you can end up in
+ * situations like "!!f ... . ... f r ..." where f is an extension update function.
+ * In order to split "f r" we transform this to "!!r ... . ... r ..." so that the
+ * usual split rules for extensions can apply.
+ *)
+val record_split_f_more_simproc =
+ Simplifier.simproc @{theory HOL} "record_split_f_more_simp" ["x"]
+ (fn thy => fn _ => fn t =>
+ (case t of (Const ("all", Type (_, [Type (_, [Type("fun",[T,T']), _]), _])))$
+ (trm as Abs _) =>
+ (case rec_id (~1) T of
+ "" => NONE
+ | n => if T=T'
+ then (let
+ val P=cterm_of thy (abstract_over_fun_app trm);
+ val thm = mk_fun_apply_eq trm thy;
+ val PV = cterm_of thy (hd (OldTerm.term_vars (prop_of thm)));
+ val thm' = cterm_instantiate [(PV,P)] thm;
+ in SOME thm' end handle TERM _ => NONE)
+ else NONE)
+ | _ => NONE))
+end
+
+fun prove_split_simp thy ss T prop =
+ let
+ val {sel_upd={simpset,...},extsplit,...} = RecordsData.get thy;
+ val extsplits =
+ Library.foldl (fn (thms,(n,_)) => the_list (Symtab.lookup extsplit n) @ thms)
+ ([],dest_recTs T);
+ val thms = (case get_splits thy (rec_id (~1) T) of
+ SOME (all_thm,_,_,_) =>
+ all_thm::(case extsplits of [thm] => [] | _ => extsplits)
+ (* [thm] is the same as all_thm *)
+ | NONE => extsplits)
+ val thms'=K_comp_convs@thms;
+ val ss' = (Simplifier.inherit_context ss simpset
+ addsimps thms'
+ addsimprocs [record_split_f_more_simproc]);
+ in
+ quick_and_dirty_prove true thy [] prop (fn _ => simp_tac ss' 1)
+ end;
+
+
+local
+fun eq (s1:string) (s2:string) = (s1 = s2);
+fun has_field extfields f T =
+ exists (fn (eN,_) => exists (eq f o fst) (Symtab.lookup_list extfields eN))
+ (dest_recTs T);
+
+fun K_skeleton n (T as Type (_,[_,kT])) (b as Bound i) (Abs (x,xT,t)) =
+ if null (loose_bnos t) then ((n,kT),(Abs (x,xT,Bound (i+1)))) else ((n,T),b)
+ | K_skeleton n T b _ = ((n,T),b);
+
+(*
+fun K_skeleton n _ b ((K_rec as Const ("Record.K_record",Type (_,[kT,_])))$_) =
+ ((n,kT),K_rec$b)
+ | K_skeleton n _ (Bound i)
+ (Abs (x,T,(K_rec as Const ("Record.K_record",Type (_,[kT,_])))$_$Bound 0)) =
+ ((n,kT),Abs (x,T,(K_rec$Bound (i+1)$Bound 0)))
+ | K_skeleton n T b _ = ((n,T),b);
+ *)
+
+fun normalize_rhs thm =
+ let
+ val ss = HOL_basic_ss addsimps K_comp_convs;
+ val rhs = thm |> Thm.cprop_of |> Thm.dest_comb |> snd;
+ val rhs' = (Simplifier.rewrite ss rhs);
+ in Thm.transitive thm rhs' end;
+in
+(* record_simproc *)
+(* Simplifies selections of an record update:
+ * (1) S (S_update k r) = k (S r)
+ * (2) S (X_update k r) = S r
+ * The simproc skips multiple updates at once, eg:
+ * S (X_update x (Y_update y (S_update k r))) = k (S r)
+ * But be careful in (2) because of the extendibility of records.
+ * - If S is a more-selector we have to make sure that the update on component
+ * X does not affect the selected subrecord.
+ * - If X is a more-selector we have to make sure that S is not in the updated
+ * subrecord.
+ *)
+val record_simproc =
+ Simplifier.simproc @{theory HOL} "record_simp" ["x"]
+ (fn thy => fn ss => fn t =>
+ (case t of (sel as Const (s, Type (_,[domS,rangeS])))$
+ ((upd as Const (u,Type(_,[_,Type (_,[rT,_])]))) $ k $ r)=>
+ if is_selector thy s then
+ (case get_updates thy u of SOME u_name =>
+ let
+ val {sel_upd={updates,...},extfields,...} = RecordsData.get thy;
+
+ fun mk_eq_terms ((upd as Const (u,Type(_,[kT,_]))) $ k $ r) =
+ (case Symtab.lookup updates u of
+ NONE => NONE
+ | SOME u_name
+ => if u_name = s
+ then (case mk_eq_terms r of
+ NONE =>
+ let
+ val rv = ("r",rT)
+ val rb = Bound 0
+ val (kv,kb) = K_skeleton "k" kT (Bound 1) k;
+ in SOME (upd$kb$rb,kb$(sel$rb),[kv,rv]) end
+ | SOME (trm,trm',vars) =>
+ let
+ val (kv,kb) = K_skeleton "k" kT (Bound (length vars)) k;
+ in SOME (upd$kb$trm,kb$trm',kv::vars) end)
+ else if has_field extfields u_name rangeS
+ orelse has_field extfields s (domain_type kT)
+ then NONE
+ else (case mk_eq_terms r of
+ SOME (trm,trm',vars)
+ => let
+ val (kv,kb) =
+ K_skeleton "k" kT (Bound (length vars)) k;
+ in SOME (upd$kb$trm,trm',kv::vars) end
+ | NONE
+ => let
+ val rv = ("r",rT)
+ val rb = Bound 0
+ val (kv,kb) = K_skeleton "k" kT (Bound 1) k;
+ in SOME (upd$kb$rb,sel$rb,[kv,rv]) end))
+ | mk_eq_terms r = NONE
+ in
+ (case mk_eq_terms (upd$k$r) of
+ SOME (trm,trm',vars)
+ => SOME (prove_split_simp thy ss domS
+ (list_all(vars, Logic.mk_equals (sel $ trm, trm'))))
+ | NONE => NONE)
+ end
+ | NONE => NONE)
+ else NONE
+ | _ => NONE));
+
+(* record_upd_simproc *)
+(* simplify multiple updates:
+ * (1) "N_update y (M_update g (N_update x (M_update f r))) =
+ (N_update (y o x) (M_update (g o f) r))"
+ * (2) "r(|M:= M r|) = r"
+ * For (2) special care of "more" updates has to be taken:
+ * r(|more := m; A := A r|)
+ * If A is contained in the fields of m we cannot remove the update A := A r!
+ * (But r(|more := r; A := A (r(|more := r|))|) = r(|more := r|)
+*)
+val record_upd_simproc =
+ Simplifier.simproc @{theory HOL} "record_upd_simp" ["x"]
+ (fn thy => fn ss => fn t =>
+ (case t of ((upd as Const (u, Type(_,[_,Type(_,[rT,_])]))) $ k $ r) =>
+ let datatype ('a,'b) calc = Init of 'b | Inter of 'a
+ val {sel_upd={selectors,updates,...},extfields,...} = RecordsData.get thy;
+
+ (*fun mk_abs_var x t = (x, fastype_of t);*)
+ fun sel_name u = Long_Name.base_name (unsuffix updateN u);
+
+ fun seed s (upd as Const (more,Type(_,[mT,_]))$ k $ r) =
+ if has_field extfields s (domain_type' mT) then upd else seed s r
+ | seed _ r = r;
+
+ fun grow u uT k kT vars (sprout,skeleton) =
+ if sel_name u = moreN
+ then let val (kv,kb) = K_skeleton "k" kT (Bound (length vars)) k;
+ in ((Const (u,uT)$k$sprout,Const (u,uT)$kb$skeleton),kv::vars) end
+ else ((sprout,skeleton),vars);
+
+
+ fun dest_k (Abs (x,T,((sel as Const (s,_))$r))) =
+ if null (loose_bnos r) then SOME (x,T,sel,s,r) else NONE
+ | dest_k (Abs (_,_,(Abs (x,T,((sel as Const (s,_))$r)))$Bound 0)) =
+ (* eta expanded variant *)
+ if null (loose_bnos r) then SOME (x,T,sel,s,r) else NONE
+ | dest_k _ = NONE;
+
+ fun is_upd_same (sprout,skeleton) u k =
+ (case dest_k k of SOME (x,T,sel,s,r) =>
+ if (unsuffix updateN u) = s andalso (seed s sprout) = r
+ then SOME (fn t => Abs (x,T,incr_boundvars 1 t),sel,seed s skeleton)
+ else NONE
+ | NONE => NONE);
+
+ fun init_seed r = ((r,Bound 0), [("r", rT)]);
+
+ fun add (n:string) f fmaps =
+ (case AList.lookup (op =) fmaps n of
+ NONE => AList.update (op =) (n,[f]) fmaps
+ | SOME fs => AList.update (op =) (n,f::fs) fmaps)
+
+ fun comps (n:string) T fmaps =
+ (case AList.lookup (op =) fmaps n of
+ SOME fs =>
+ foldr1 (fn (f,g) => Const ("Fun.comp",(T-->T)-->(T-->T)-->(T-->T))$f$g) fs
+ | NONE => error ("record_upd_simproc.comps"))
+
+ (* mk_updterm returns either
+ * - Init (orig-term, orig-term-skeleton, vars) if no optimisation can be made,
+ * where vars are the bound variables in the skeleton
+ * - Inter (orig-term-skeleton,simplified-term-skeleton,
+ * vars, (term-sprout, skeleton-sprout))
+ * where "All vars. orig-term-skeleton = simplified-term-skeleton" is
+ * the desired simplification rule,
+ * the sprouts accumulate the "more-updates" on the way from the seed
+ * to the outermost update. It is only relevant to calculate the
+ * possible simplification for (2)
+ * The algorithm first walks down the updates to the seed-record while
+ * memorising the updates in the already-table. While walking up the
+ * updates again, the optimised term is constructed.
+ *)
+ fun mk_updterm upds already
+ (t as ((upd as Const (u,uT as (Type (_,[kT,_])))) $ k $ r)) =
+ if Symtab.defined upds u
+ then let
+ fun rest already = mk_updterm upds already
+ in if u mem_string already
+ then (case (rest already r) of
+ Init ((sprout,skel),vars) =>
+ let
+ val n = sel_name u;
+ val (kv,kb) = K_skeleton n kT (Bound (length vars)) k;
+ val (sprout',vars')= grow u uT k kT (kv::vars) (sprout,skel);
+ in Inter (upd$kb$skel,skel,vars',add n kb [],sprout') end
+ | Inter (trm,trm',vars,fmaps,sprout) =>
+ let
+ val n = sel_name u;
+ val (kv,kb) = K_skeleton n kT (Bound (length vars)) k;
+ val (sprout',vars') = grow u uT k kT (kv::vars) sprout;
+ in Inter(upd$kb$trm,trm',kv::vars',add n kb fmaps,sprout')
+ end)
+ else
+ (case rest (u::already) r of
+ Init ((sprout,skel),vars) =>
+ (case is_upd_same (sprout,skel) u k of
+ SOME (K_rec,sel,skel') =>
+ let
+ val (sprout',vars') = grow u uT k kT vars (sprout,skel);
+ in Inter(upd$(K_rec (sel$skel'))$skel,skel,vars',[],sprout')
+ end
+ | NONE =>
+ let
+ val n = sel_name u;
+ val (kv,kb) = K_skeleton n kT (Bound (length vars)) k;
+ in Init ((upd$k$sprout,upd$kb$skel),kv::vars) end)
+ | Inter (trm,trm',vars,fmaps,sprout) =>
+ (case is_upd_same sprout u k of
+ SOME (K_rec,sel,skel) =>
+ let
+ val (sprout',vars') = grow u uT k kT vars sprout
+ in Inter(upd$(K_rec (sel$skel))$trm,trm',vars',fmaps,sprout')
+ end
+ | NONE =>
+ let
+ val n = sel_name u
+ val T = domain_type kT
+ val (kv,kb) = K_skeleton n kT (Bound (length vars)) k;
+ val (sprout',vars') = grow u uT k kT (kv::vars) sprout
+ val fmaps' = add n kb fmaps
+ in Inter (upd$kb$trm,upd$comps n T fmaps'$trm'
+ ,vars',fmaps',sprout') end))
+ end
+ else Init (init_seed t)
+ | mk_updterm _ _ t = Init (init_seed t);
+
+ in (case mk_updterm updates [] t of
+ Inter (trm,trm',vars,_,_)
+ => SOME (normalize_rhs
+ (prove_split_simp thy ss rT
+ (list_all(vars, Logic.mk_equals (trm, trm')))))
+ | _ => NONE)
+ end
+ | _ => NONE))
+end
+
+(* record_eq_simproc *)
+(* looks up the most specific record-equality.
+ * Note on efficiency:
+ * Testing equality of records boils down to the test of equality of all components.
+ * Therefore the complexity is: #components * complexity for single component.
+ * Especially if a record has a lot of components it may be better to split up
+ * the record first and do simplification on that (record_split_simp_tac).
+ * e.g. r(|lots of updates|) = x
+ *
+ * record_eq_simproc record_split_simp_tac
+ * Complexity: #components * #updates #updates
+ *
+ *)
+val record_eq_simproc =
+ Simplifier.simproc @{theory HOL} "record_eq_simp" ["r = s"]
+ (fn thy => fn _ => fn t =>
+ (case t of Const ("op =", Type (_, [T, _])) $ _ $ _ =>
+ (case rec_id (~1) T of
+ "" => NONE
+ | name => (case get_equalities thy name of
+ NONE => NONE
+ | SOME thm => SOME (thm RS Eq_TrueI)))
+ | _ => NONE));
+
+(* record_split_simproc *)
+(* splits quantified occurrences of records, for which P holds. P can peek on the
+ * subterm starting at the quantified occurrence of the record (including the quantifier)
+ * P t = 0: do not split
+ * P t = ~1: completely split
+ * P t > 0: split up to given bound of record extensions
+ *)
+fun record_split_simproc P =
+ Simplifier.simproc @{theory HOL} "record_split_simp" ["x"]
+ (fn thy => fn _ => fn t =>
+ (case t of (Const (quantifier, Type (_, [Type (_, [T, _]), _])))$trm =>
+ if quantifier = "All" orelse quantifier = "all" orelse quantifier = "Ex"
+ then (case rec_id (~1) T of
+ "" => NONE
+ | name
+ => let val split = P t
+ in if split <> 0 then
+ (case get_splits thy (rec_id split T) of
+ NONE => NONE
+ | SOME (all_thm, All_thm, Ex_thm,_)
+ => SOME (case quantifier of
+ "all" => all_thm
+ | "All" => All_thm RS eq_reflection
+ | "Ex" => Ex_thm RS eq_reflection
+ | _ => error "record_split_simproc"))
+ else NONE
+ end)
+ else NONE
+ | _ => NONE))
+
+val record_ex_sel_eq_simproc =
+ Simplifier.simproc @{theory HOL} "record_ex_sel_eq_simproc" ["Ex t"]
+ (fn thy => fn ss => fn t =>
+ let
+ fun prove prop =
+ quick_and_dirty_prove true thy [] prop
+ (fn _ => simp_tac (Simplifier.inherit_context ss (get_simpset thy)
+ addsimps simp_thms addsimprocs [record_split_simproc (K ~1)]) 1);
+
+ fun mkeq (lr,Teq,(sel,Tsel),x) i =
+ if is_selector thy sel then
+ let val x' = if not (loose_bvar1 (x,0))
+ then Free ("x" ^ string_of_int i, range_type Tsel)
+ else raise TERM ("",[x]);
+ val sel' = Const (sel,Tsel)$Bound 0;
+ val (l,r) = if lr then (sel',x') else (x',sel');
+ in Const ("op =",Teq)$l$r end
+ else raise TERM ("",[Const (sel,Tsel)]);
+
+ fun dest_sel_eq (Const ("op =",Teq)$(Const (sel,Tsel)$Bound 0)$X) =
+ (true,Teq,(sel,Tsel),X)
+ | dest_sel_eq (Const ("op =",Teq)$X$(Const (sel,Tsel)$Bound 0)) =
+ (false,Teq,(sel,Tsel),X)
+ | dest_sel_eq _ = raise TERM ("",[]);
+
+ in
+ (case t of
+ (Const ("Ex",Tex)$Abs(s,T,t)) =>
+ (let val eq = mkeq (dest_sel_eq t) 0;
+ val prop = list_all ([("r",T)],
+ Logic.mk_equals (Const ("Ex",Tex)$Abs(s,T,eq),
+ HOLogic.true_const));
+ in SOME (prove prop) end
+ handle TERM _ => NONE)
+ | _ => NONE)
+ end)
+
+
+
+
+local
+val inductive_atomize = thms "induct_atomize";
+val inductive_rulify = thms "induct_rulify";
+in
+(* record_split_simp_tac *)
+(* splits (and simplifies) all records in the goal for which P holds.
+ * For quantified occurrences of a record
+ * P can peek on the whole subterm (including the quantifier); for free variables P
+ * can only peek on the variable itself.
+ * P t = 0: do not split
+ * P t = ~1: completely split
+ * P t > 0: split up to given bound of record extensions
+ *)
+fun record_split_simp_tac thms P i st =
+ let
+ val thy = Thm.theory_of_thm st;
+
+ val has_rec = exists_Const
+ (fn (s, Type (_, [Type (_, [T, _]), _])) =>
+ (s = "all" orelse s = "All" orelse s = "Ex") andalso is_recT T
+ | _ => false);
+
+ val goal = nth (Thm.prems_of st) (i - 1);
+ val frees = List.filter (is_recT o type_of) (OldTerm.term_frees goal);
+
+ fun mk_split_free_tac free induct_thm i =
+ let val cfree = cterm_of thy free;
+ val (_$(_$r)) = concl_of induct_thm;
+ val crec = cterm_of thy r;
+ val thm = cterm_instantiate [(crec,cfree)] induct_thm;
+ in EVERY [simp_tac (HOL_basic_ss addsimps inductive_atomize) i,
+ rtac thm i,
+ simp_tac (HOL_basic_ss addsimps inductive_rulify) i]
+ end;
+
+ fun split_free_tac P i (free as Free (n,T)) =
+ (case rec_id (~1) T of
+ "" => NONE
+ | name => let val split = P free
+ in if split <> 0 then
+ (case get_splits thy (rec_id split T) of
+ NONE => NONE
+ | SOME (_,_,_,induct_thm)
+ => SOME (mk_split_free_tac free induct_thm i))
+ else NONE
+ end)
+ | split_free_tac _ _ _ = NONE;
+
+ val split_frees_tacs = List.mapPartial (split_free_tac P i) frees;
+
+ val simprocs = if has_rec goal then [record_split_simproc P] else [];
+ val thms' = K_comp_convs@thms
+ in st |> ((EVERY split_frees_tacs)
+ THEN (Simplifier.full_simp_tac (get_simpset thy addsimps thms' addsimprocs simprocs) i))
+ end handle Empty => Seq.empty;
+end;
+
+
+(* record_split_tac *)
+(* splits all records in the goal, which are quantified by ! or !!. *)
+fun record_split_tac i st =
+ let
+ val thy = Thm.theory_of_thm st;
+
+ val has_rec = exists_Const
+ (fn (s, Type (_, [Type (_, [T, _]), _])) =>
+ (s = "all" orelse s = "All") andalso is_recT T
+ | _ => false);
+
+ val goal = nth (Thm.prems_of st) (i - 1);
+
+ fun is_all t =
+ (case t of (Const (quantifier, _)$_) =>
+ if quantifier = "All" orelse quantifier = "all" then ~1 else 0
+ | _ => 0);
+
+ in if has_rec goal
+ then Simplifier.full_simp_tac
+ (HOL_basic_ss addsimprocs [record_split_simproc is_all]) i st
+ else Seq.empty
+ end handle Subscript => Seq.empty;
+
+(* wrapper *)
+
+val record_split_name = "record_split_tac";
+val record_split_wrapper = (record_split_name, fn tac => record_split_tac ORELSE' tac);
+
+
+
+(** theory extender interface **)
+
+(* prepare arguments *)
+
+fun read_raw_parent ctxt raw_T =
+ (case ProofContext.read_typ_abbrev ctxt raw_T of
+ Type (name, Ts) => (Ts, name)
+ | T => error ("Bad parent record specification: " ^ Syntax.string_of_typ ctxt T));
+
+fun read_typ ctxt raw_T env =
+ let
+ val ctxt' = fold (Variable.declare_typ o TFree) env ctxt;
+ val T = Syntax.read_typ ctxt' raw_T;
+ val env' = OldTerm.add_typ_tfrees (T, env);
+ in (T, env') end;
+
+fun cert_typ ctxt raw_T env =
+ let
+ val thy = ProofContext.theory_of ctxt;
+ val T = Type.no_tvars (Sign.certify_typ thy raw_T) handle TYPE (msg, _, _) => error msg;
+ val env' = OldTerm.add_typ_tfrees (T, env);
+ in (T, env') end;
+
+
+(* attributes *)
+
+fun case_names_fields x = RuleCases.case_names ["fields"] x;
+fun induct_type_global name = [case_names_fields, Induct.induct_type name];
+fun cases_type_global name = [case_names_fields, Induct.cases_type name];
+
+(* tactics *)
+
+fun simp_all_tac ss simps = ALLGOALS (Simplifier.asm_full_simp_tac (ss addsimps simps));
+
+(* do case analysis / induction according to rule on last parameter of ith subgoal
+ * (or on s if there are no parameters);
+ * Instatiation of record variable (and predicate) in rule is calculated to
+ * avoid problems with higher order unification.
+ *)
+
+fun try_param_tac s rule i st =
+ let
+ val cert = cterm_of (Thm.theory_of_thm st);
+ val g = nth (prems_of st) (i - 1);
+ val params = Logic.strip_params g;
+ val concl = HOLogic.dest_Trueprop (Logic.strip_assums_concl g);
+ val rule' = Thm.lift_rule (Thm.cprem_of st i) rule;
+ val (P, ys) = strip_comb (HOLogic.dest_Trueprop
+ (Logic.strip_assums_concl (prop_of rule')));
+ (* ca indicates if rule is a case analysis or induction rule *)
+ val (x, ca) = (case rev (Library.drop (length params, ys)) of
+ [] => (head_of (fst (HOLogic.dest_eq (HOLogic.dest_Trueprop
+ (hd (rev (Logic.strip_assums_hyp (hd (prems_of rule')))))))), true)
+ | [x] => (head_of x, false));
+ val rule'' = cterm_instantiate (map (pairself cert) (case (rev params) of
+ [] => (case AList.lookup (op =) (map dest_Free (OldTerm.term_frees (prop_of st))) s of
+ NONE => sys_error "try_param_tac: no such variable"
+ | SOME T => [(P, if ca then concl else lambda (Free (s, T)) concl),
+ (x, Free (s, T))])
+ | (_, T) :: _ => [(P, list_abs (params, if ca then concl
+ else incr_boundvars 1 (Abs (s, T, concl)))),
+ (x, list_abs (params, Bound 0))])) rule'
+ in compose_tac (false, rule'', nprems_of rule) i st end;
+
+
+(* !!x1 ... xn. ... ==> EX x1 ... xn. P x1 ... xn;
+ instantiates x1 ... xn with parameters x1 ... xn *)
+fun ex_inst_tac i st =
+ let
+ val thy = Thm.theory_of_thm st;
+ val g = nth (prems_of st) (i - 1);
+ val params = Logic.strip_params g;
+ val exI' = Thm.lift_rule (Thm.cprem_of st i) exI;
+ val (_$(_$x)) = Logic.strip_assums_concl (hd (prems_of exI'));
+ val cx = cterm_of thy (fst (strip_comb x));
+
+ in Seq.single (Library.foldl (fn (st,v) =>
+ Seq.hd
+ (compose_tac (false, cterm_instantiate
+ [(cx,cterm_of thy (list_abs (params,Bound v)))] exI',1)
+ i st)) (st,((length params) - 1) downto 0))
+ end;
+
+fun extension_typedef name repT alphas thy =
+ let
+ fun get_thms thy name =
+ let
+ val SOME { Abs_induct = abs_induct,
+ Abs_inject=abs_inject, Abs_inverse = abs_inverse, ...} = Typedef.get_info thy name;
+ val rewrite_rule = MetaSimplifier.rewrite_rule [rec_UNIV_I, rec_True_simp];
+ in map rewrite_rule [abs_inject, abs_inverse, abs_induct] end;
+ val tname = Binding.name (Long_Name.base_name name);
+ in
+ thy
+ |> Typecopy.typecopy (Binding.suffix_name ext_typeN tname, alphas) repT NONE
+ |-> (fn (name, _) => `(fn thy => get_thms thy name))
+ end;
+
+fun mixit convs refls =
+ let fun f ((res,lhs,rhs),refl) = ((refl,List.revAppend (lhs,refl::tl rhs))::res,hd rhs::lhs,tl rhs);
+ in #1 (Library.foldl f (([],[],convs),refls)) end;
+
+
+fun extension_definition full name fields names alphas zeta moreT more vars thy =
+ let
+ val base = Long_Name.base_name;
+ val fieldTs = (map snd fields);
+ val alphas_zeta = alphas@[zeta];
+ val alphas_zetaTs = map (fn n => TFree (n, HOLogic.typeS)) alphas_zeta;
+ val vT = TFree (Name.variant alphas_zeta "'v", HOLogic.typeS);
+ val extT_name = suffix ext_typeN name
+ val extT = Type (extT_name, alphas_zetaTs);
+ val repT = foldr1 HOLogic.mk_prodT (fieldTs@[moreT]);
+ val fields_more = fields@[(full moreN,moreT)];
+ val fields_moreTs = fieldTs@[moreT];
+ val bfields_more = map (apfst base) fields_more;
+ val r = Free (rN,extT)
+ val len = length fields;
+ val idxms = 0 upto len;
+
+ (* prepare declarations and definitions *)
+
+ (*fields constructor*)
+ val ext_decl = (mk_extC (name,extT) fields_moreTs);
+ (*
+ val ext_spec = Const ext_decl :==
+ (foldr (uncurry lambda)
+ (mk_Abs name repT extT $ (foldr1 HOLogic.mk_prod (vars@[more]))) (vars@[more]))
+ *)
+ val ext_spec = list_comb (Const ext_decl,vars@[more]) :==
+ (mk_Abs name repT extT $ (foldr1 HOLogic.mk_prod (vars@[more])));
+
+ fun mk_ext args = list_comb (Const ext_decl, args);
+
+ (*destructors*)
+ val _ = timing_msg "record extension preparing definitions";
+ val dest_decls = map (mk_selC extT o (apfst (suffix ext_dest))) bfields_more;
+
+ fun mk_dest_spec (i, (c,T)) =
+ let val snds = (funpow i HOLogic.mk_snd (mk_Rep name repT extT $ r))
+ in Const (mk_selC extT (suffix ext_dest c,T))
+ :== (lambda r (if i=len then snds else HOLogic.mk_fst snds))
+ end;
+ val dest_specs =
+ ListPair.map mk_dest_spec (idxms, fields_more);
+
+ (*updates*)
+ val upd_decls = map (mk_updC updN extT) bfields_more;
+ fun mk_upd_spec (c,T) =
+ let
+ val args = map (fn (n,nT) => if n=c then Free (base c,T --> T)$
+ (mk_sel r (suffix ext_dest n,nT))
+ else (mk_sel r (suffix ext_dest n,nT)))
+ fields_more;
+ in Const (mk_updC updN extT (c,T))$(Free (base c,T --> T))$r
+ :== mk_ext args
+ end;
+ val upd_specs = map mk_upd_spec fields_more;
+
+ (* 1st stage: defs_thy *)
+ fun mk_defs () =
+ thy
+ |> extension_typedef name repT (alphas @ [zeta])
+ ||> Sign.add_consts_i
+ (map (Syntax.no_syn o apfst Binding.name) (apfst base ext_decl :: dest_decls @ upd_decls))
+ ||>> PureThy.add_defs false
+ (map (Thm.no_attributes o apfst Binding.name) (ext_spec :: dest_specs))
+ ||>> PureThy.add_defs false
+ (map (Thm.no_attributes o apfst Binding.name) upd_specs)
+ |-> (fn args as ((_, dest_defs), upd_defs) =>
+ fold Code.add_default_eqn dest_defs
+ #> fold Code.add_default_eqn upd_defs
+ #> pair args);
+ val ((([abs_inject, abs_inverse, abs_induct], ext_def :: dest_defs), upd_defs), defs_thy) =
+ timeit_msg "record extension type/selector/update defs:" mk_defs;
+
+ (* prepare propositions *)
+ val _ = timing_msg "record extension preparing propositions";
+ val vars_more = vars@[more];
+ val named_vars_more = (names@[full moreN])~~vars_more;
+ val variants = map (fn (Free (x,_))=>x) vars_more;
+ val ext = mk_ext vars_more;
+ val s = Free (rN, extT);
+ val w = Free (wN, extT);
+ val P = Free (Name.variant variants "P", extT-->HOLogic.boolT);
+ val C = Free (Name.variant variants "C", HOLogic.boolT);
+
+ val inject_prop =
+ let val vars_more' = map (fn (Free (x,T)) => Free (x ^ "'",T)) vars_more;
+ in All (map dest_Free (vars_more@vars_more'))
+ ((HOLogic.eq_const extT $
+ mk_ext vars_more$mk_ext vars_more')
+ ===
+ foldr1 HOLogic.mk_conj (map HOLogic.mk_eq (vars_more ~~ vars_more')))
+ end;
+
+ val induct_prop =
+ (All (map dest_Free vars_more) (Trueprop (P $ ext)), Trueprop (P $ s));
+
+ val cases_prop =
+ (All (map dest_Free vars_more)
+ (Trueprop (HOLogic.mk_eq (s,ext)) ==> Trueprop C))
+ ==> Trueprop C;
+
+ (*destructors*)
+ val dest_conv_props =
+ map (fn (c, x as Free (_,T)) => mk_sel ext (suffix ext_dest c,T) === x) named_vars_more;
+
+ (*updates*)
+ fun mk_upd_prop (i,(c,T)) =
+ let val x' = Free (Name.variant variants (base c ^ "'"),T --> T)
+ val args' = nth_map i (K (x'$nth vars_more i)) vars_more
+ in mk_upd updN c x' ext === mk_ext args' end;
+ val upd_conv_props = ListPair.map mk_upd_prop (idxms, fields_more);
+
+ val surjective_prop =
+ let val args =
+ map (fn (c, Free (_,T)) => mk_sel s (suffix ext_dest c,T)) named_vars_more;
+ in s === mk_ext args end;
+
+ val split_meta_prop =
+ let val P = Free (Name.variant variants "P", extT-->Term.propT) in
+ Logic.mk_equals
+ (All [dest_Free s] (P $ s), All (map dest_Free vars_more) (P $ ext))
+ end;
+
+ fun prove stndrd = quick_and_dirty_prove stndrd defs_thy;
+ val prove_standard = quick_and_dirty_prove true defs_thy;
+ fun prove_simp stndrd simps =
+ let val tac = simp_all_tac HOL_ss simps
+ in fn prop => prove stndrd [] prop (K tac) end;
+
+ fun inject_prf () = (prove_simp true [ext_def,abs_inject,Pair_eq] inject_prop);
+ val inject = timeit_msg "record extension inject proof:" inject_prf;
+
+ fun induct_prf () =
+ let val (assm, concl) = induct_prop
+ in prove_standard [assm] concl (fn {prems, ...} =>
+ EVERY [try_param_tac rN abs_induct 1,
+ simp_tac (HOL_ss addsimps [split_paired_all]) 1,
+ resolve_tac (map (rewrite_rule [ext_def]) prems) 1])
+ end;
+ val induct = timeit_msg "record extension induct proof:" induct_prf;
+
+ fun cases_prf_opt () =
+ let
+ val (_$(Pvar$_)) = concl_of induct;
+ val ind = cterm_instantiate
+ [(cterm_of defs_thy Pvar, cterm_of defs_thy
+ (lambda w (HOLogic.imp$HOLogic.mk_eq(r,w)$C)))]
+ induct;
+ in standard (ObjectLogic.rulify (mp OF [ind, refl])) end;
+
+ fun cases_prf_noopt () =
+ prove_standard [] cases_prop (fn _ =>
+ EVERY [asm_full_simp_tac (HOL_basic_ss addsimps [atomize_all, atomize_imp]) 1,
+ try_param_tac rN induct 1,
+ rtac impI 1,
+ REPEAT (etac allE 1),
+ etac mp 1,
+ rtac refl 1])
+
+ val cases_prf = quick_and_dirty_prf cases_prf_noopt cases_prf_opt;
+ val cases = timeit_msg "record extension cases proof:" cases_prf;
+
+ fun dest_convs_prf () = map (prove_simp false
+ ([ext_def,abs_inverse]@Pair_sel_convs@dest_defs)) dest_conv_props;
+ val dest_convs = timeit_msg "record extension dest_convs proof:" dest_convs_prf;
+ fun dest_convs_standard_prf () = map standard dest_convs;
+
+ val dest_convs_standard =
+ timeit_msg "record extension dest_convs_standard proof:" dest_convs_standard_prf;
+
+ fun upd_convs_prf_noopt () = map (prove_simp true (dest_convs_standard@upd_defs))
+ upd_conv_props;
+ fun upd_convs_prf_opt () =
+ let
+
+ fun mkrefl (c,T) = Thm.reflexive
+ (cterm_of defs_thy (Free (Name.variant variants (base c ^ "'"),T-->T)));
+ val refls = map mkrefl fields_more;
+ val dest_convs' = map mk_meta_eq dest_convs;
+ val map_eqs = map (uncurry Thm.combination) (refls ~~ dest_convs');
+
+ val constr_refl = Thm.reflexive (cterm_of defs_thy (head_of ext));
+
+ fun mkthm (udef,(fld_refl,thms)) =
+ let val bdyeq = Library.foldl (uncurry Thm.combination) (constr_refl,thms);
+ (* (|N=N (|N=N,M=M,K=K,more=more|)
+ M=M (|N=N,M=M,K=K,more=more|)
+ K=K'
+ more = more (|N=N,M=M,K=K,more=more|) =
+ (|N=N,M=M,K=K',more=more|)
+ *)
+ val (_$(_$v$r)$_) = prop_of udef;
+ val (_$(v'$_)$_) = prop_of fld_refl;
+ val udef' = cterm_instantiate
+ [(cterm_of defs_thy v,cterm_of defs_thy v'),
+ (cterm_of defs_thy r,cterm_of defs_thy ext)] udef;
+ in standard (Thm.transitive udef' bdyeq) end;
+ in map mkthm (rev upd_defs ~~ (mixit dest_convs' map_eqs)) end;
+
+ val upd_convs_prf = quick_and_dirty_prf upd_convs_prf_noopt upd_convs_prf_opt;
+
+ val upd_convs =
+ timeit_msg "record extension upd_convs proof:" upd_convs_prf;
+
+ fun surjective_prf () =
+ prove_standard [] surjective_prop (fn _ =>
+ (EVERY [try_param_tac rN induct 1,
+ simp_tac (HOL_basic_ss addsimps dest_convs_standard) 1]));
+ val surjective = timeit_msg "record extension surjective proof:" surjective_prf;
+
+ fun split_meta_prf () =
+ prove_standard [] split_meta_prop (fn _ =>
+ EVERY [rtac equal_intr_rule 1, Goal.norm_hhf_tac 1,
+ etac meta_allE 1, atac 1,
+ rtac (prop_subst OF [surjective]) 1,
+ REPEAT (etac meta_allE 1), atac 1]);
+ val split_meta = timeit_msg "record extension split_meta proof:" split_meta_prf;
+
+
+ val (([inject',induct',cases',surjective',split_meta'],
+ [dest_convs',upd_convs']),
+ thm_thy) =
+ defs_thy
+ |> (PureThy.add_thms o map (Thm.no_attributes o apfst Binding.name))
+ [("ext_inject", inject),
+ ("ext_induct", induct),
+ ("ext_cases", cases),
+ ("ext_surjective", surjective),
+ ("ext_split", split_meta)]
+ ||>> (PureThy.add_thmss o map (Thm.no_attributes o apfst Binding.name))
+ [("dest_convs", dest_convs_standard), ("upd_convs", upd_convs)]
+
+ in (thm_thy,extT,induct',inject',dest_convs',split_meta',upd_convs')
+ end;
+
+fun chunks [] [] = []
+ | chunks [] xs = [xs]
+ | chunks (l::ls) xs = Library.take (l,xs)::chunks ls (Library.drop (l,xs));
+
+fun chop_last [] = error "last: list should not be empty"
+ | chop_last [x] = ([],x)
+ | chop_last (x::xs) = let val (tl,l) = chop_last xs in (x::tl,l) end;
+
+fun subst_last s [] = error "subst_last: list should not be empty"
+ | subst_last s ([x]) = [s]
+ | subst_last s (x::xs) = (x::subst_last s xs);
+
+(* mk_recordT builds up the record type from the current extension tpye extT and a list
+ * of parent extensions, starting with the root of the record hierarchy
+*)
+fun mk_recordT extT =
+ fold_rev (fn (parent, Ts) => fn T => Type (parent, subst_last T Ts)) extT;
+
+
+
+fun obj_to_meta_all thm =
+ let
+ fun E thm = case (SOME (spec OF [thm]) handle THM _ => NONE) of
+ SOME thm' => E thm'
+ | NONE => thm;
+ val th1 = E thm;
+ val th2 = Drule.forall_intr_vars th1;
+ in th2 end;
+
+fun meta_to_obj_all thm =
+ let
+ val thy = Thm.theory_of_thm thm;
+ val prop = Thm.prop_of thm;
+ val params = Logic.strip_params prop;
+ val concl = HOLogic.dest_Trueprop (Logic.strip_assums_concl prop);
+ val ct = cterm_of thy
+ (HOLogic.mk_Trueprop (HOLogic.list_all (params, concl)));
+ val thm' = Seq.hd (REPEAT (rtac allI 1) (Thm.trivial ct));
+ in
+ Thm.implies_elim thm' thm
+ end;
+
+
+
+(* record_definition *)
+
+fun record_definition (args, bname) parent (parents: parent_info list) raw_fields thy =
+ let
+ val external_names = NameSpace.external_names (Sign.naming_of thy);
+
+ val alphas = map fst args;
+ val name = Sign.full_bname thy bname;
+ val full = Sign.full_bname_path thy bname;
+ val base = Long_Name.base_name;
+
+ val (bfields, field_syntax) = split_list (map (fn (x, T, mx) => ((x, T), mx)) raw_fields);
+
+ val parent_fields = List.concat (map #fields parents);
+ val parent_chunks = map (length o #fields) parents;
+ val parent_names = map fst parent_fields;
+ val parent_types = map snd parent_fields;
+ val parent_fields_len = length parent_fields;
+ val parent_variants = Name.variant_list [moreN, rN, rN ^ "'", wN] (map base parent_names);
+ val parent_vars = ListPair.map Free (parent_variants, parent_types);
+ val parent_len = length parents;
+ val parents_idx = (map #name parents) ~~ (0 upto (parent_len - 1));
+
+ val fields = map (apfst full) bfields;
+ val names = map fst fields;
+ val extN = full bname;
+ val types = map snd fields;
+ val alphas_fields = List.foldr OldTerm.add_typ_tfree_names [] types;
+ val alphas_ext = alphas inter alphas_fields;
+ val len = length fields;
+ val variants =
+ Name.variant_list (moreN :: rN :: (rN ^ "'") :: wN :: parent_variants) (map fst bfields);
+ val vars = ListPair.map Free (variants, types);
+ val named_vars = names ~~ vars;
+ val idxs = 0 upto (len - 1);
+ val idxms = 0 upto len;
+
+ val all_fields = parent_fields @ fields;
+ val all_names = parent_names @ names;
+ val all_types = parent_types @ types;
+ val all_len = parent_fields_len + len;
+ val all_variants = parent_variants @ variants;
+ val all_vars = parent_vars @ vars;
+ val all_named_vars = (parent_names ~~ parent_vars) @ named_vars;
+
+
+ val zeta = Name.variant alphas "'z";
+ val moreT = TFree (zeta, HOLogic.typeS);
+ val more = Free (moreN, moreT);
+ val full_moreN = full moreN;
+ val bfields_more = bfields @ [(moreN,moreT)];
+ val fields_more = fields @ [(full_moreN,moreT)];
+ val vars_more = vars @ [more];
+ val named_vars_more = named_vars @[(full_moreN,more)];
+ val all_vars_more = all_vars @ [more];
+ val all_named_vars_more = all_named_vars @ [(full_moreN,more)];
+
+ (* 1st stage: extension_thy *)
+ val (extension_thy,extT,ext_induct,ext_inject,ext_dest_convs,ext_split,u_convs) =
+ thy
+ |> Sign.add_path bname
+ |> extension_definition full extN fields names alphas_ext zeta moreT more vars;
+
+ val _ = timing_msg "record preparing definitions";
+ val Type extension_scheme = extT;
+ val extension_name = unsuffix ext_typeN (fst extension_scheme);
+ val extension = let val (n,Ts) = extension_scheme in (n,subst_last HOLogic.unitT Ts) end;
+ val extension_names =
+ (map ((unsuffix ext_typeN) o fst o #extension) parents) @ [extN];
+ val extension_id = Library.foldl (op ^) ("",extension_names);
+
+
+ fun rec_schemeT n = mk_recordT (map #extension (prune n parents)) extT;
+ val rec_schemeT0 = rec_schemeT 0;
+
+ fun recT n =
+ let val (c,Ts) = extension
+ in mk_recordT (map #extension (prune n parents)) (Type (c,subst_last HOLogic.unitT Ts))
+ end;
+ val recT0 = recT 0;
+
+ fun mk_rec args n =
+ let val (args',more) = chop_last args;
+ fun mk_ext' (((name,T),args),more) = mk_ext (name,T) (args@[more]);
+ fun build Ts =
+ List.foldr mk_ext' more (prune n (extension_names ~~ Ts ~~ (chunks parent_chunks args')))
+ in
+ if more = HOLogic.unit
+ then build (map recT (0 upto parent_len))
+ else build (map rec_schemeT (0 upto parent_len))
+ end;
+
+ val r_rec0 = mk_rec all_vars_more 0;
+ val r_rec_unit0 = mk_rec (all_vars@[HOLogic.unit]) 0;
+
+ fun r n = Free (rN, rec_schemeT n)
+ val r0 = r 0;
+ fun r_unit n = Free (rN, recT n)
+ val r_unit0 = r_unit 0;
+ val w = Free (wN, rec_schemeT 0)
+
+ (* prepare print translation functions *)
+ val field_tr's =
+ print_translation (distinct (op =) (maps external_names (full_moreN :: names)));
+
+ val adv_ext_tr's =
+ let
+ val trnames = external_names extN;
+ in map (gen_record_tr') trnames end;
+
+ val adv_record_type_abbr_tr's =
+ let val trnames = external_names (hd extension_names);
+ val lastExt = unsuffix ext_typeN (fst extension);
+ in map (gen_record_type_abbr_tr' name alphas zeta lastExt rec_schemeT0) trnames
+ end;
+
+ val adv_record_type_tr's =
+ let val trnames = if parent_len > 0 then external_names extN else [];
+ (* avoid conflict with adv_record_type_abbr_tr's *)
+ in map (gen_record_type_tr') trnames
+ end;
+
+
+ (* prepare declarations *)
+
+ val sel_decls = map (mk_selC rec_schemeT0) bfields_more;
+ val upd_decls = map (mk_updC updateN rec_schemeT0) bfields_more;
+ val make_decl = (makeN, all_types ---> recT0);
+ val fields_decl = (fields_selN, types ---> Type extension);
+ val extend_decl = (extendN, recT0 --> moreT --> rec_schemeT0);
+ val truncate_decl = (truncateN, rec_schemeT0 --> recT0);
+
+ (* prepare definitions *)
+
+ fun parent_more s =
+ if null parents then s
+ else mk_sel s (Long_Name.qualify (#name (List.last parents)) moreN, extT);
+
+ fun parent_more_upd v s =
+ if null parents then v$s
+ else let val mp = Long_Name.qualify (#name (List.last parents)) moreN;
+ in mk_upd updateN mp v s end;
+
+ (*record (scheme) type abbreviation*)
+ val recordT_specs =
+ [(Binding.name (suffix schemeN bname), alphas @ [zeta], rec_schemeT0, Syntax.NoSyn),
+ (Binding.name bname, alphas, recT0, Syntax.NoSyn)];
+
+ (*selectors*)
+ fun mk_sel_spec (c,T) =
+ Const (mk_selC rec_schemeT0 (c,T))
+ :== (lambda r0 (Const (mk_selC extT (suffix ext_dest c,T))$parent_more r0));
+ val sel_specs = map mk_sel_spec fields_more;
+
+ (*updates*)
+
+ fun mk_upd_spec (c,T) =
+ let
+ val new = mk_upd' updN c (Free (base c,T-->T)) extT(*(parent_more r0)*);
+ in Const (mk_updC updateN rec_schemeT0 (c,T))$(Free (base c,T-->T))$r0
+ :== (parent_more_upd new r0)
+ end;
+ val upd_specs = map mk_upd_spec fields_more;
+
+ (*derived operations*)
+ val make_spec = Const (full makeN, all_types ---> recT0) $$ all_vars :==
+ mk_rec (all_vars @ [HOLogic.unit]) 0;
+ val fields_spec = Const (full fields_selN, types ---> Type extension) $$ vars :==
+ mk_rec (all_vars @ [HOLogic.unit]) parent_len;
+ val extend_spec =
+ Const (full extendN, recT0-->moreT-->rec_schemeT0) $ r_unit0 $ more :==
+ mk_rec ((map (mk_sel r_unit0) all_fields) @ [more]) 0;
+ val truncate_spec = Const (full truncateN, rec_schemeT0 --> recT0) $ r0 :==
+ mk_rec ((map (mk_sel r0) all_fields) @ [HOLogic.unit]) 0;
+
+ (* 2st stage: defs_thy *)
+
+ fun mk_defs () =
+ extension_thy
+ |> Sign.add_trfuns
+ ([],[],field_tr's, [])
+ |> Sign.add_advanced_trfuns
+ ([],[],adv_ext_tr's @ adv_record_type_tr's @ adv_record_type_abbr_tr's,[])
+ |> Sign.parent_path
+ |> Sign.add_tyabbrs_i recordT_specs
+ |> Sign.add_path bname
+ |> Sign.add_consts_i
+ (map2 (fn (x, T) => fn mx => (Binding.name x, T, mx))
+ sel_decls (field_syntax @ [Syntax.NoSyn]))
+ |> (Sign.add_consts_i o map (fn (x, T) => (Binding.name x, T, Syntax.NoSyn)))
+ (upd_decls @ [make_decl, fields_decl, extend_decl, truncate_decl])
+ |> ((PureThy.add_defs false o map (Thm.no_attributes o apfst Binding.name)) sel_specs)
+ ||>> ((PureThy.add_defs false o map (Thm.no_attributes o apfst Binding.name)) upd_specs)
+ ||>> ((PureThy.add_defs false o map (Thm.no_attributes o apfst Binding.name))
+ [make_spec, fields_spec, extend_spec, truncate_spec])
+ |-> (fn defs as ((sel_defs, upd_defs), derived_defs) =>
+ fold Code.add_default_eqn sel_defs
+ #> fold Code.add_default_eqn upd_defs
+ #> fold Code.add_default_eqn derived_defs
+ #> pair defs)
+ val (((sel_defs, upd_defs), derived_defs), defs_thy) =
+ timeit_msg "record trfuns/tyabbrs/selectors/updates/make/fields/extend/truncate defs:"
+ mk_defs;
+
+
+ (* prepare propositions *)
+ val _ = timing_msg "record preparing propositions";
+ val P = Free (Name.variant all_variants "P", rec_schemeT0-->HOLogic.boolT);
+ val C = Free (Name.variant all_variants "C", HOLogic.boolT);
+ val P_unit = Free (Name.variant all_variants "P", recT0-->HOLogic.boolT);
+
+ (*selectors*)
+ val sel_conv_props =
+ map (fn (c, x as Free (_,T)) => mk_sel r_rec0 (c,T) === x) named_vars_more;
+
+ (*updates*)
+ fun mk_upd_prop (i,(c,T)) =
+ let val x' = Free (Name.variant all_variants (base c ^ "'"),T-->T);
+ val n = parent_fields_len + i;
+ val args' = nth_map n (K (x'$nth all_vars_more n)) all_vars_more
+ in mk_upd updateN c x' r_rec0 === mk_rec args' 0 end;
+ val upd_conv_props = ListPair.map mk_upd_prop (idxms, fields_more);
+
+ (*induct*)
+ val induct_scheme_prop =
+ All (map dest_Free all_vars_more) (Trueprop (P $ r_rec0)) ==> Trueprop (P $ r0);
+ val induct_prop =
+ (All (map dest_Free all_vars) (Trueprop (P_unit $ r_rec_unit0)),
+ Trueprop (P_unit $ r_unit0));
+
+ (*surjective*)
+ val surjective_prop =
+ let val args = map (fn (c,Free (_,T)) => mk_sel r0 (c,T)) all_named_vars_more
+ in r0 === mk_rec args 0 end;
+
+ (*cases*)
+ val cases_scheme_prop =
+ (All (map dest_Free all_vars_more)
+ (Trueprop (HOLogic.mk_eq (r0,r_rec0)) ==> Trueprop C))
+ ==> Trueprop C;
+
+ val cases_prop =
+ (All (map dest_Free all_vars)
+ (Trueprop (HOLogic.mk_eq (r_unit0,r_rec_unit0)) ==> Trueprop C))
+ ==> Trueprop C;
+
+ (*split*)
+ val split_meta_prop =
+ let val P = Free (Name.variant all_variants "P", rec_schemeT0-->Term.propT) in
+ Logic.mk_equals
+ (All [dest_Free r0] (P $ r0), All (map dest_Free all_vars_more) (P $ r_rec0))
+ end;
+
+ val split_object_prop =
+ let fun ALL vs t = List.foldr (fn ((v,T),t) => HOLogic.mk_all (v,T,t)) t vs
+ in (ALL [dest_Free r0] (P $ r0)) === (ALL (map dest_Free all_vars_more) (P $ r_rec0))
+ end;
+
+
+ val split_ex_prop =
+ let fun EX vs t = List.foldr (fn ((v,T),t) => HOLogic.mk_exists (v,T,t)) t vs
+ in (EX [dest_Free r0] (P $ r0)) === (EX (map dest_Free all_vars_more) (P $ r_rec0))
+ end;
+
+ (*equality*)
+ val equality_prop =
+ let
+ val s' = Free (rN ^ "'", rec_schemeT0)
+ fun mk_sel_eq (c,Free (_,T)) = mk_sel r0 (c,T) === mk_sel s' (c,T)
+ val seleqs = map mk_sel_eq all_named_vars_more
+ in All (map dest_Free [r0,s']) (Logic.list_implies (seleqs,r0 === s')) end;
+
+ (* 3rd stage: thms_thy *)
+
+ fun prove stndrd = quick_and_dirty_prove stndrd defs_thy;
+ val prove_standard = quick_and_dirty_prove true defs_thy;
+
+ fun prove_simp stndrd ss simps =
+ let val tac = simp_all_tac ss simps
+ in fn prop => prove stndrd [] prop (K tac) end;
+
+ val ss = get_simpset defs_thy;
+
+ fun sel_convs_prf () = map (prove_simp false ss
+ (sel_defs@ext_dest_convs)) sel_conv_props;
+ val sel_convs = timeit_msg "record sel_convs proof:" sel_convs_prf;
+ fun sel_convs_standard_prf () = map standard sel_convs
+ val sel_convs_standard =
+ timeit_msg "record sel_convs_standard proof:" sel_convs_standard_prf;
+
+ fun upd_convs_prf () =
+ map (prove_simp true ss (upd_defs@u_convs)) upd_conv_props;
+
+ val upd_convs = timeit_msg "record upd_convs proof:" upd_convs_prf;
+
+ val parent_induct = if null parents then [] else [#induct (hd (rev parents))];
+
+ fun induct_scheme_prf () = prove_standard [] induct_scheme_prop (fn _ =>
+ (EVERY [if null parent_induct
+ then all_tac else try_param_tac rN (hd parent_induct) 1,
+ try_param_tac rN ext_induct 1,
+ asm_simp_tac HOL_basic_ss 1]));
+ val induct_scheme = timeit_msg "record induct_scheme proof:" induct_scheme_prf;
+
+ fun induct_prf () =
+ let val (assm, concl) = induct_prop;
+ in
+ prove_standard [assm] concl (fn {prems, ...} =>
+ try_param_tac rN induct_scheme 1
+ THEN try_param_tac "more" @{thm unit.induct} 1
+ THEN resolve_tac prems 1)
+ end;
+ val induct = timeit_msg "record induct proof:" induct_prf;
+
+ fun surjective_prf () =
+ prove_standard [] surjective_prop (fn prems =>
+ (EVERY [try_param_tac rN induct_scheme 1,
+ simp_tac (ss addsimps sel_convs_standard) 1]))
+ val surjective = timeit_msg "record surjective proof:" surjective_prf;
+
+ fun cases_scheme_prf_opt () =
+ let
+ val (_$(Pvar$_)) = concl_of induct_scheme;
+ val ind = cterm_instantiate
+ [(cterm_of defs_thy Pvar, cterm_of defs_thy
+ (lambda w (HOLogic.imp$HOLogic.mk_eq(r0,w)$C)))]
+ induct_scheme;
+ in standard (ObjectLogic.rulify (mp OF [ind, refl])) end;
+
+ fun cases_scheme_prf_noopt () =
+ prove_standard [] cases_scheme_prop (fn _ =>
+ EVERY [asm_full_simp_tac (HOL_basic_ss addsimps [atomize_all, atomize_imp]) 1,
+ try_param_tac rN induct_scheme 1,
+ rtac impI 1,
+ REPEAT (etac allE 1),
+ etac mp 1,
+ rtac refl 1])
+ val cases_scheme_prf = quick_and_dirty_prf cases_scheme_prf_noopt cases_scheme_prf_opt;
+ val cases_scheme = timeit_msg "record cases_scheme proof:" cases_scheme_prf;
+
+ fun cases_prf () =
+ prove_standard [] cases_prop (fn _ =>
+ try_param_tac rN cases_scheme 1
+ THEN simp_all_tac HOL_basic_ss [unit_all_eq1]);
+ val cases = timeit_msg "record cases proof:" cases_prf;
+
+ fun split_meta_prf () =
+ prove false [] split_meta_prop (fn _ =>
+ EVERY [rtac equal_intr_rule 1, Goal.norm_hhf_tac 1,
+ etac meta_allE 1, atac 1,
+ rtac (prop_subst OF [surjective]) 1,
+ REPEAT (etac meta_allE 1), atac 1]);
+ val split_meta = timeit_msg "record split_meta proof:" split_meta_prf;
+ val split_meta_standard = standard split_meta;
+
+ fun split_object_prf_opt () =
+ let
+ val cPI= cterm_of defs_thy (lambda r0 (Trueprop (P$r0)));
+ val (_$Abs(_,_,P$_)) = fst (Logic.dest_equals (concl_of split_meta_standard));
+ val cP = cterm_of defs_thy P;
+ val split_meta' = cterm_instantiate [(cP,cPI)] split_meta_standard;
+ val (l,r) = HOLogic.dest_eq (HOLogic.dest_Trueprop split_object_prop);
+ val cl = cterm_of defs_thy (HOLogic.mk_Trueprop l);
+ val cr = cterm_of defs_thy (HOLogic.mk_Trueprop r);
+ val thl = assume cl (*All r. P r*) (* 1 *)
+ |> obj_to_meta_all (*!!r. P r*)
+ |> equal_elim split_meta' (*!!n m more. P (ext n m more)*)
+ |> meta_to_obj_all (*All n m more. P (ext n m more)*) (* 2*)
+ |> implies_intr cl (* 1 ==> 2 *)
+ val thr = assume cr (*All n m more. P (ext n m more)*)
+ |> obj_to_meta_all (*!!n m more. P (ext n m more)*)
+ |> equal_elim (symmetric split_meta') (*!!r. P r*)
+ |> meta_to_obj_all (*All r. P r*)
+ |> implies_intr cr (* 2 ==> 1 *)
+ in standard (thr COMP (thl COMP iffI)) end;
+
+ fun split_object_prf_noopt () =
+ prove_standard [] split_object_prop (fn _ =>
+ EVERY [rtac iffI 1,
+ REPEAT (rtac allI 1), etac allE 1, atac 1,
+ rtac allI 1, rtac induct_scheme 1,REPEAT (etac allE 1),atac 1]);
+
+ val split_object_prf = quick_and_dirty_prf split_object_prf_noopt split_object_prf_opt;
+ val split_object = timeit_msg "record split_object proof:" split_object_prf;
+
+
+ fun split_ex_prf () =
+ prove_standard [] split_ex_prop (fn _ =>
+ EVERY [rtac iffI 1,
+ etac exE 1,
+ simp_tac (HOL_basic_ss addsimps [split_meta_standard]) 1,
+ ex_inst_tac 1,
+ (*REPEAT (rtac exI 1),*)
+ atac 1,
+ REPEAT (etac exE 1),
+ rtac exI 1,
+ atac 1]);
+ val split_ex = timeit_msg "record split_ex proof:" split_ex_prf;
+
+ fun equality_tac thms =
+ let val (s'::s::eqs) = rev thms;
+ val ss' = ss addsimps (s'::s::sel_convs_standard);
+ val eqs' = map (simplify ss') eqs;
+ in simp_tac (HOL_basic_ss addsimps (s'::s::eqs')) 1 end;
+
+ fun equality_prf () = prove_standard [] equality_prop (fn {context, ...} =>
+ fn st => let val [s, s'] = map #1 (rev (Tactic.innermost_params 1 st)) in
+ st |> (res_inst_tac context [((rN, 0), s)] cases_scheme 1
+ THEN res_inst_tac context [((rN, 0), s')] cases_scheme 1
+ THEN (METAHYPS equality_tac 1))
+ (* simp_all_tac ss (sel_convs) would also work but is less efficient *)
+ end);
+ val equality = timeit_msg "record equality proof:" equality_prf;
+
+ val ((([sel_convs',upd_convs',sel_defs',upd_defs',[split_meta',split_object',split_ex'],derived_defs'],
+ [surjective',equality']),[induct_scheme',induct',cases_scheme',cases']), thms_thy) =
+ defs_thy
+ |> (PureThy.add_thmss o map (Thm.no_attributes o apfst Binding.name))
+ [("select_convs", sel_convs_standard),
+ ("update_convs", upd_convs),
+ ("select_defs", sel_defs),
+ ("update_defs", upd_defs),
+ ("splits", [split_meta_standard,split_object,split_ex]),
+ ("defs", derived_defs)]
+ ||>> (PureThy.add_thms o map (Thm.no_attributes o apfst Binding.name))
+ [("surjective", surjective),
+ ("equality", equality)]
+ ||>> (PureThy.add_thms o (map o apfst o apfst) Binding.name)
+ [(("induct_scheme", induct_scheme), induct_type_global (suffix schemeN name)),
+ (("induct", induct), induct_type_global name),
+ (("cases_scheme", cases_scheme), cases_type_global (suffix schemeN name)),
+ (("cases", cases), cases_type_global name)];
+
+
+ val sel_upd_simps = sel_convs' @ upd_convs';
+ val iffs = [ext_inject]
+ val final_thy =
+ thms_thy
+ |> (snd oo PureThy.add_thmss)
+ [((Binding.name "simps", sel_upd_simps),
+ [Simplifier.simp_add, Nitpick_Const_Simp_Thms.add]),
+ ((Binding.name "iffs", iffs), [iff_add])]
+ |> put_record name (make_record_info args parent fields extension induct_scheme')
+ |> put_sel_upd (names @ [full_moreN]) sel_upd_simps
+ |> add_record_equalities extension_id equality'
+ |> add_extinjects ext_inject
+ |> add_extsplit extension_name ext_split
+ |> add_record_splits extension_id (split_meta',split_object',split_ex',induct_scheme')
+ |> add_extfields extension_name (fields @ [(full_moreN,moreT)])
+ |> add_fieldext (extension_name,snd extension) (names @ [full_moreN])
+ |> Sign.parent_path;
+
+ in final_thy
+ end;
+
+
+(* add_record *)
+
+(*we do all preparations and error checks here, deferring the real
+ work to record_definition*)
+fun gen_add_record prep_typ prep_raw_parent quiet_mode (params, bname) raw_parent raw_fields thy =
+ let
+ val _ = Theory.requires thy "Record" "record definitions";
+ val _ = if quiet_mode then () else writeln ("Defining record " ^ quote bname ^ " ...");
+
+ val ctxt = ProofContext.init thy;
+
+
+ (* parents *)
+
+ fun prep_inst T = fst (cert_typ ctxt T []);
+
+ val parent = Option.map (apfst (map prep_inst) o prep_raw_parent ctxt) raw_parent
+ handle ERROR msg => cat_error msg ("The error(s) above in parent record specification");
+ val parents = add_parents thy parent [];
+
+ val init_env =
+ (case parent of
+ NONE => []
+ | SOME (types, _) => List.foldr OldTerm.add_typ_tfrees [] types);
+
+
+ (* fields *)
+
+ fun prep_field (c, raw_T, mx) env =
+ let val (T, env') = prep_typ ctxt raw_T env handle ERROR msg =>
+ cat_error msg ("The error(s) above occured in record field " ^ quote c)
+ in ((c, T, mx), env') end;
+
+ val (bfields, envir) = fold_map prep_field raw_fields init_env;
+ val envir_names = map fst envir;
+
+
+ (* args *)
+
+ val defaultS = Sign.defaultS thy;
+ val args = map (fn x => (x, AList.lookup (op =) envir x |> the_default defaultS)) params;
+
+
+ (* errors *)
+
+ val name = Sign.full_bname thy bname;
+ val err_dup_record =
+ if is_none (get_record thy name) then []
+ else ["Duplicate definition of record " ^ quote name];
+
+ val err_dup_parms =
+ (case duplicates (op =) params of
+ [] => []
+ | dups => ["Duplicate parameter(s) " ^ commas dups]);
+
+ val err_extra_frees =
+ (case subtract (op =) params envir_names of
+ [] => []
+ | extras => ["Extra free type variable(s) " ^ commas extras]);
+
+ val err_no_fields = if null bfields then ["No fields present"] else [];
+
+ val err_dup_fields =
+ (case duplicates (op =) (map #1 bfields) of
+ [] => []
+ | dups => ["Duplicate field(s) " ^ commas_quote dups]);
+
+ val err_bad_fields =
+ if forall (not_equal moreN o #1) bfields then []
+ else ["Illegal field name " ^ quote moreN];
+
+ val err_dup_sorts =
+ (case duplicates (op =) envir_names of
+ [] => []
+ | dups => ["Inconsistent sort constraints for " ^ commas dups]);
+
+ val errs =
+ err_dup_record @ err_dup_parms @ err_extra_frees @ err_no_fields @
+ err_dup_fields @ err_bad_fields @ err_dup_sorts;
+ in
+ if null errs then () else error (cat_lines errs) ;
+ thy |> record_definition (args, bname) parent parents bfields
+ end
+ handle ERROR msg => cat_error msg ("Failed to define record " ^ quote bname);
+
+val add_record = gen_add_record read_typ read_raw_parent;
+val add_record_i = gen_add_record cert_typ (K I);
+
+(* setup theory *)
+
+val setup =
+ Sign.add_trfuns ([], parse_translation, [], []) #>
+ Sign.add_advanced_trfuns ([], adv_parse_translation, [], []) #>
+ Simplifier.map_simpset (fn ss =>
+ ss addsimprocs [record_simproc, record_upd_simproc, record_eq_simproc]);
+
+(* outer syntax *)
+
+local structure P = OuterParse and K = OuterKeyword in
+
+val record_decl =
+ P.type_args -- P.name --
+ (P.$$$ "=" |-- Scan.option (P.typ --| P.$$$ "+") -- Scan.repeat1 P.const);
+
+val _ =
+ OuterSyntax.command "record" "define extensible record" K.thy_decl
+ (record_decl >> (fn (x, (y, z)) => Toplevel.theory (add_record false x y z)));
+
+end;
+
+end;
+
+
+structure BasicRecord: BASIC_RECORD = Record;
+open BasicRecord;
--- a/src/HOL/Tools/record_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2325 +0,0 @@
-(* Title: HOL/Tools/record_package.ML
- Author: Wolfgang Naraschewski, Norbert Schirmer and Markus Wenzel, TU Muenchen
-
-Extensible records with structural subtyping in HOL.
-*)
-
-
-signature BASIC_RECORD_PACKAGE =
-sig
- val record_simproc: simproc
- val record_eq_simproc: simproc
- val record_upd_simproc: simproc
- val record_split_simproc: (term -> int) -> simproc
- val record_ex_sel_eq_simproc: simproc
- val record_split_tac: int -> tactic
- val record_split_simp_tac: thm list -> (term -> int) -> int -> tactic
- val record_split_name: string
- val record_split_wrapper: string * wrapper
- val print_record_type_abbr: bool ref
- val print_record_type_as_fields: bool ref
-end;
-
-signature RECORD_PACKAGE =
-sig
- include BASIC_RECORD_PACKAGE
- val timing: bool ref
- val record_quick_and_dirty_sensitive: bool ref
- val updateN: string
- val updN: string
- val ext_typeN: string
- val extN: string
- val makeN: string
- val moreN: string
- val ext_dest: string
-
- val last_extT: typ -> (string * typ list) option
- val dest_recTs : typ -> (string * typ list) list
- val get_extT_fields: theory -> typ -> (string * typ) list * (string * typ)
- val get_recT_fields: theory -> typ -> (string * typ) list * (string * typ)
- val get_parent: theory -> string -> (typ list * string) option
- val get_extension: theory -> string -> (string * typ list) option
- val get_extinjects: theory -> thm list
- val get_simpset: theory -> simpset
- val print_records: theory -> unit
- val read_typ: Proof.context -> string -> (string * sort) list -> typ * (string * sort) list
- val cert_typ: Proof.context -> typ -> (string * sort) list -> typ * (string * sort) list
- val add_record: bool -> string list * string -> string option -> (string * string * mixfix) list
- -> theory -> theory
- val add_record_i: bool -> string list * string -> (typ list * string) option
- -> (string * typ * mixfix) list -> theory -> theory
- val setup: theory -> theory
-end;
-
-
-structure RecordPackage: RECORD_PACKAGE =
-struct
-
-val eq_reflection = thm "eq_reflection";
-val rec_UNIV_I = thm "rec_UNIV_I";
-val rec_True_simp = thm "rec_True_simp";
-val Pair_eq = thm "Product_Type.prod.inject";
-val atomize_all = thm "HOL.atomize_all";
-val atomize_imp = thm "HOL.atomize_imp";
-val meta_allE = thm "Pure.meta_allE";
-val prop_subst = thm "prop_subst";
-val Pair_sel_convs = [fst_conv,snd_conv];
-val K_record_comp = @{thm "K_record_comp"};
-val K_comp_convs = [@{thm o_apply}, K_record_comp]
-
-(** name components **)
-
-val rN = "r";
-val wN = "w";
-val moreN = "more";
-val schemeN = "_scheme";
-val ext_typeN = "_ext_type";
-val extN ="_ext";
-val casesN = "_cases";
-val ext_dest = "_sel";
-val updateN = "_update";
-val updN = "_upd";
-val makeN = "make";
-val fields_selN = "fields";
-val extendN = "extend";
-val truncateN = "truncate";
-
-(*see typedef_package.ML*)
-val RepN = "Rep_";
-val AbsN = "Abs_";
-
-(*** utilities ***)
-
-fun but_last xs = fst (split_last xs);
-
-fun varifyT midx =
- let fun varify (a, S) = TVar ((a, midx + 1), S);
- in map_type_tfree varify end;
-
-fun domain_type' T =
- domain_type T handle Match => T;
-
-fun range_type' T =
- range_type T handle Match => T;
-
-(* messages *)
-
-fun trace_thm str thm =
- tracing (str ^ (Pretty.string_of (Display.pretty_thm thm)));
-
-fun trace_thms str thms =
- (tracing str; map (trace_thm "") thms);
-
-fun trace_term str t =
- tracing (str ^ Syntax.string_of_term_global Pure.thy t);
-
-(* timing *)
-
-val timing = ref false;
-fun timeit_msg s x = if !timing then (warning s; timeit x) else x ();
-fun timing_msg s = if !timing then warning s else ();
-
-(* syntax *)
-
-fun prune n xs = Library.drop (n, xs);
-fun prefix_base s = Long_Name.map_base_name (fn bname => s ^ bname);
-
-val Trueprop = HOLogic.mk_Trueprop;
-fun All xs t = Term.list_all_free (xs, t);
-
-infix 9 $$;
-infix 0 :== ===;
-infixr 0 ==>;
-
-val (op $$) = Term.list_comb;
-val (op :==) = PrimitiveDefs.mk_defpair;
-val (op ===) = Trueprop o HOLogic.mk_eq;
-val (op ==>) = Logic.mk_implies;
-
-(* morphisms *)
-
-fun mk_RepN name = suffix ext_typeN (prefix_base RepN name);
-fun mk_AbsN name = suffix ext_typeN (prefix_base AbsN name);
-
-fun mk_Rep name repT absT =
- Const (suffix ext_typeN (prefix_base RepN name),absT --> repT);
-
-fun mk_Abs name repT absT =
- Const (mk_AbsN name,repT --> absT);
-
-(* constructor *)
-
-fun mk_extC (name,T) Ts = (suffix extN name, Ts ---> T);
-
-fun mk_ext (name,T) ts =
- let val Ts = map fastype_of ts
- in list_comb (Const (mk_extC (name,T) Ts),ts) end;
-
-(* cases *)
-
-fun mk_casesC (name,T,vT) Ts = (suffix casesN name, (Ts ---> vT) --> T --> vT)
-
-fun mk_cases (name,T,vT) f =
- let val Ts = binder_types (fastype_of f)
- in Const (mk_casesC (name,T,vT) Ts) $ f end;
-
-(* selector *)
-
-fun mk_selC sT (c,T) = (c,sT --> T);
-
-fun mk_sel s (c,T) =
- let val sT = fastype_of s
- in Const (mk_selC sT (c,T)) $ s end;
-
-(* updates *)
-
-fun mk_updC sfx sT (c,T) = (suffix sfx c, (T --> T) --> sT --> sT);
-
-fun mk_upd' sfx c v sT =
- let val vT = domain_type (fastype_of v);
- in Const (mk_updC sfx sT (c, vT)) $ v end;
-
-fun mk_upd sfx c v s = mk_upd' sfx c v (fastype_of s) $ s
-
-(* types *)
-
-fun dest_recT (typ as Type (c_ext_type, Ts as (T::_))) =
- (case try (unsuffix ext_typeN) c_ext_type of
- NONE => raise TYPE ("RecordPackage.dest_recT", [typ], [])
- | SOME c => ((c, Ts), List.last Ts))
- | dest_recT typ = raise TYPE ("RecordPackage.dest_recT", [typ], []);
-
-fun is_recT T =
- (case try dest_recT T of NONE => false | SOME _ => true);
-
-fun dest_recTs T =
- let val ((c, Ts), U) = dest_recT T
- in (c, Ts) :: dest_recTs U
- end handle TYPE _ => [];
-
-fun last_extT T =
- let val ((c, Ts), U) = dest_recT T
- in (case last_extT U of
- NONE => SOME (c,Ts)
- | SOME l => SOME l)
- end handle TYPE _ => NONE
-
-fun rec_id i T =
- let val rTs = dest_recTs T
- val rTs' = if i < 0 then rTs else Library.take (i,rTs)
- in Library.foldl (fn (s,(c,T)) => s ^ c) ("",rTs') end;
-
-(*** extend theory by record definition ***)
-
-(** record info **)
-
-(* type record_info and parent_info *)
-
-type record_info =
- {args: (string * sort) list,
- parent: (typ list * string) option,
- fields: (string * typ) list,
- extension: (string * typ list),
- induct: thm
- };
-
-fun make_record_info args parent fields extension induct =
- {args = args, parent = parent, fields = fields, extension = extension,
- induct = induct}: record_info;
-
-
-type parent_info =
- {name: string,
- fields: (string * typ) list,
- extension: (string * typ list),
- induct: thm
-};
-
-fun make_parent_info name fields extension induct =
- {name = name, fields = fields, extension = extension, induct = induct}: parent_info;
-
-
-(* theory data *)
-
-type record_data =
- {records: record_info Symtab.table,
- sel_upd:
- {selectors: unit Symtab.table,
- updates: string Symtab.table,
- simpset: Simplifier.simpset},
- equalities: thm Symtab.table,
- extinjects: thm list,
- extsplit: thm Symtab.table, (* maps extension name to split rule *)
- splits: (thm*thm*thm*thm) Symtab.table, (* !!,!,EX - split-equalities,induct rule *)
- extfields: (string*typ) list Symtab.table, (* maps extension to its fields *)
- fieldext: (string*typ list) Symtab.table (* maps field to its extension *)
-};
-
-fun make_record_data
- records sel_upd equalities extinjects extsplit splits extfields fieldext =
- {records = records, sel_upd = sel_upd,
- equalities = equalities, extinjects=extinjects, extsplit = extsplit, splits = splits,
- extfields = extfields, fieldext = fieldext }: record_data;
-
-structure RecordsData = TheoryDataFun
-(
- type T = record_data;
- val empty =
- make_record_data Symtab.empty
- {selectors = Symtab.empty, updates = Symtab.empty, simpset = HOL_basic_ss}
- Symtab.empty [] Symtab.empty Symtab.empty Symtab.empty Symtab.empty;
-
- val copy = I;
- val extend = I;
- fun merge _
- ({records = recs1,
- sel_upd = {selectors = sels1, updates = upds1, simpset = ss1},
- equalities = equalities1,
- extinjects = extinjects1,
- extsplit = extsplit1,
- splits = splits1,
- extfields = extfields1,
- fieldext = fieldext1},
- {records = recs2,
- sel_upd = {selectors = sels2, updates = upds2, simpset = ss2},
- equalities = equalities2,
- extinjects = extinjects2,
- extsplit = extsplit2,
- splits = splits2,
- extfields = extfields2,
- fieldext = fieldext2}) =
- make_record_data
- (Symtab.merge (K true) (recs1, recs2))
- {selectors = Symtab.merge (K true) (sels1, sels2),
- updates = Symtab.merge (K true) (upds1, upds2),
- simpset = Simplifier.merge_ss (ss1, ss2)}
- (Symtab.merge Thm.eq_thm_prop (equalities1, equalities2))
- (Library.merge Thm.eq_thm_prop (extinjects1, extinjects2))
- (Symtab.merge Thm.eq_thm_prop (extsplit1,extsplit2))
- (Symtab.merge (fn ((a,b,c,d),(w,x,y,z))
- => Thm.eq_thm (a,w) andalso Thm.eq_thm (b,x) andalso
- Thm.eq_thm (c,y) andalso Thm.eq_thm (d,z))
- (splits1, splits2))
- (Symtab.merge (K true) (extfields1,extfields2))
- (Symtab.merge (K true) (fieldext1,fieldext2));
-);
-
-fun print_records thy =
- let
- val {records = recs, ...} = RecordsData.get thy;
- val prt_typ = Syntax.pretty_typ_global thy;
-
- fun pretty_parent NONE = []
- | pretty_parent (SOME (Ts, name)) =
- [Pretty.block [prt_typ (Type (name, Ts)), Pretty.str " +"]];
-
- fun pretty_field (c, T) = Pretty.block
- [Pretty.str (Sign.extern_const thy c), Pretty.str " ::",
- Pretty.brk 1, Pretty.quote (prt_typ T)];
-
- fun pretty_record (name, {args, parent, fields, ...}: record_info) =
- Pretty.block (Pretty.fbreaks (Pretty.block
- [prt_typ (Type (name, map TFree args)), Pretty.str " = "] ::
- pretty_parent parent @ map pretty_field fields));
- in map pretty_record (Symtab.dest recs) |> Pretty.chunks |> Pretty.writeln end;
-
-
-(* access 'records' *)
-
-val get_record = Symtab.lookup o #records o RecordsData.get;
-
-fun put_record name info thy =
- let
- val {records, sel_upd, equalities, extinjects,extsplit,splits,extfields,fieldext} =
- RecordsData.get thy;
- val data = make_record_data (Symtab.update (name, info) records)
- sel_upd equalities extinjects extsplit splits extfields fieldext;
- in RecordsData.put data thy end;
-
-
-(* access 'sel_upd' *)
-
-val get_sel_upd = #sel_upd o RecordsData.get;
-
-val is_selector = Symtab.defined o #selectors o get_sel_upd;
-val get_updates = Symtab.lookup o #updates o get_sel_upd;
-fun get_simpset thy = Simplifier.theory_context thy (#simpset (get_sel_upd thy));
-
-fun put_sel_upd names simps = RecordsData.map (fn {records,
- sel_upd = {selectors, updates, simpset},
- equalities, extinjects, extsplit, splits, extfields, fieldext} =>
- make_record_data records
- {selectors = fold (fn name => Symtab.update (name, ())) names selectors,
- updates = fold (fn name => Symtab.update ((suffix updateN) name, name)) names updates,
- simpset = Simplifier.addsimps (simpset, simps)}
- equalities extinjects extsplit splits extfields fieldext);
-
-
-(* access 'equalities' *)
-
-fun add_record_equalities name thm thy =
- let
- val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields,fieldext} =
- RecordsData.get thy;
- val data = make_record_data records sel_upd
- (Symtab.update_new (name, thm) equalities) extinjects extsplit
- splits extfields fieldext;
- in RecordsData.put data thy end;
-
-val get_equalities =Symtab.lookup o #equalities o RecordsData.get;
-
-
-(* access 'extinjects' *)
-
-fun add_extinjects thm thy =
- let
- val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields,fieldext} =
- RecordsData.get thy;
- val data =
- make_record_data records sel_upd equalities (insert Thm.eq_thm_prop thm extinjects) extsplit
- splits extfields fieldext;
- in RecordsData.put data thy end;
-
-val get_extinjects = rev o #extinjects o RecordsData.get;
-
-
-(* access 'extsplit' *)
-
-fun add_extsplit name thm thy =
- let
- val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields,fieldext} =
- RecordsData.get thy;
- val data = make_record_data records sel_upd
- equalities extinjects (Symtab.update_new (name, thm) extsplit) splits
- extfields fieldext;
- in RecordsData.put data thy end;
-
-val get_extsplit = Symtab.lookup o #extsplit o RecordsData.get;
-
-
-(* access 'splits' *)
-
-fun add_record_splits name thmP thy =
- let
- val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields,fieldext} =
- RecordsData.get thy;
- val data = make_record_data records sel_upd
- equalities extinjects extsplit (Symtab.update_new (name, thmP) splits)
- extfields fieldext;
- in RecordsData.put data thy end;
-
-val get_splits = Symtab.lookup o #splits o RecordsData.get;
-
-
-(* parent/extension of named record *)
-
-val get_parent = (Option.join o Option.map #parent) oo (Symtab.lookup o #records o RecordsData.get);
-val get_extension = Option.map #extension oo (Symtab.lookup o #records o RecordsData.get);
-
-
-(* access 'extfields' *)
-
-fun add_extfields name fields thy =
- let
- val {records, sel_upd, equalities, extinjects, extsplit,splits, extfields, fieldext} =
- RecordsData.get thy;
- val data = make_record_data records sel_upd
- equalities extinjects extsplit splits
- (Symtab.update_new (name, fields) extfields) fieldext;
- in RecordsData.put data thy end;
-
-val get_extfields = Symtab.lookup o #extfields o RecordsData.get;
-
-fun get_extT_fields thy T =
- let
- val ((name,Ts),moreT) = dest_recT T;
- val recname = let val (nm::recn::rst) = rev (Long_Name.explode name)
- in Long_Name.implode (rev (nm::rst)) end;
- val midx = maxidx_of_typs (moreT::Ts);
- val varifyT = varifyT midx;
- val {records,extfields,...} = RecordsData.get thy;
- val (flds,(more,_)) = split_last (Symtab.lookup_list extfields name);
- val args = map varifyT (snd (#extension (the (Symtab.lookup records recname))));
-
- val subst = fold (Sign.typ_match thy) (but_last args ~~ but_last Ts) (Vartab.empty);
- val flds' = map (apsnd ((Envir.norm_type subst) o varifyT)) flds;
- in (flds',(more,moreT)) end;
-
-fun get_recT_fields thy T =
- let
- val (root_flds,(root_more,root_moreT)) = get_extT_fields thy T;
- val (rest_flds,rest_more) =
- if is_recT root_moreT then get_recT_fields thy root_moreT
- else ([],(root_more,root_moreT));
- in (root_flds@rest_flds,rest_more) end;
-
-
-(* access 'fieldext' *)
-
-fun add_fieldext extname_types fields thy =
- let
- val {records, sel_upd, equalities, extinjects, extsplit, splits, extfields, fieldext} =
- RecordsData.get thy;
- val fieldext' =
- fold (fn field => Symtab.update_new (field, extname_types)) fields fieldext;
- val data=make_record_data records sel_upd equalities extinjects extsplit
- splits extfields fieldext';
- in RecordsData.put data thy end;
-
-
-val get_fieldext = Symtab.lookup o #fieldext o RecordsData.get;
-
-
-(* parent records *)
-
-fun add_parents thy NONE parents = parents
- | add_parents thy (SOME (types, name)) parents =
- let
- fun err msg = error (msg ^ " parent record " ^ quote name);
-
- val {args, parent, fields, extension, induct} =
- (case get_record thy name of SOME info => info | NONE => err "Unknown");
- val _ = if length types <> length args then err "Bad number of arguments for" else ();
-
- fun bad_inst ((x, S), T) =
- if Sign.of_sort thy (T, S) then NONE else SOME x
- val bads = List.mapPartial bad_inst (args ~~ types);
- val _ = null bads orelse err ("Ill-sorted instantiation of " ^ commas bads ^ " in");
-
- val inst = map fst args ~~ types;
- val subst = Term.map_type_tfree (the o AList.lookup (op =) inst o fst);
- val parent' = Option.map (apfst (map subst)) parent;
- val fields' = map (apsnd subst) fields;
- val extension' = apsnd (map subst) extension;
- in
- add_parents thy parent'
- (make_parent_info name fields' extension' induct :: parents)
- end;
-
-
-
-(** concrete syntax for records **)
-
-(* decode type *)
-
-fun decode_type thy t =
- let
- fun get_sort xs n = AList.lookup (op =) xs (n: indexname) |> the_default (Sign.defaultS thy);
- val map_sort = Sign.intern_sort thy;
- in
- Syntax.typ_of_term (get_sort (Syntax.term_sorts map_sort t)) map_sort t
- |> Sign.intern_tycons thy
- end;
-
-
-(* parse translations *)
-
-fun gen_field_tr mark sfx (t as Const (c, _) $ Const (name, _) $ arg) =
- if c = mark then Syntax.const (suffix sfx name) $ (Abs ("_",dummyT, arg))
- else raise TERM ("gen_field_tr: " ^ mark, [t])
- | gen_field_tr mark _ t = raise TERM ("gen_field_tr: " ^ mark, [t]);
-
-fun gen_fields_tr sep mark sfx (tm as Const (c, _) $ t $ u) =
- if c = sep then gen_field_tr mark sfx t :: gen_fields_tr sep mark sfx u
- else [gen_field_tr mark sfx tm]
- | gen_fields_tr _ mark sfx tm = [gen_field_tr mark sfx tm];
-
-
-fun record_update_tr [t, u] =
- Library.foldr (op $) (rev (gen_fields_tr "_updates" "_update" updateN u), t)
- | record_update_tr ts = raise TERM ("record_update_tr", ts);
-
-fun update_name_tr (Free (x, T) :: ts) = Free (suffix updateN x, T) $$ ts
- | update_name_tr (Const (x, T) :: ts) = Const (suffix updateN x, T) $$ ts
- | update_name_tr (((c as Const ("_constrain", _)) $ t $ ty) :: ts) =
- (c $ update_name_tr [t] $ (Syntax.const "fun" $ ty $ Syntax.const "dummy")) $$ ts
- | update_name_tr ts = raise TERM ("update_name_tr", ts);
-
-fun dest_ext_field mark (t as (Const (c,_) $ Const (name,_) $ arg)) =
- if c = mark then (name,arg) else raise TERM ("dest_ext_field: " ^ mark, [t])
- | dest_ext_field _ t = raise TERM ("dest_ext_field", [t])
-
-fun dest_ext_fields sep mark (trm as (Const (c,_) $ t $ u)) =
- if c = sep then dest_ext_field mark t::dest_ext_fields sep mark u
- else [dest_ext_field mark trm]
- | dest_ext_fields _ mark t = [dest_ext_field mark t]
-
-fun gen_ext_fields_tr sep mark sfx more ctxt t =
- let
- val thy = ProofContext.theory_of ctxt;
- val msg = "error in record input: ";
- val fieldargs = dest_ext_fields sep mark t;
- fun splitargs (field::fields) ((name,arg)::fargs) =
- if can (unsuffix name) field
- then let val (args,rest) = splitargs fields fargs
- in (arg::args,rest) end
- else raise TERM (msg ^ "expecting field " ^ field ^ " but got " ^ name, [t])
- | splitargs [] (fargs as (_::_)) = ([],fargs)
- | splitargs (_::_) [] = raise TERM (msg ^ "expecting more fields", [t])
- | splitargs _ _ = ([],[]);
-
- fun mk_ext (fargs as (name,arg)::_) =
- (case get_fieldext thy (Sign.intern_const thy name) of
- SOME (ext,_) => (case get_extfields thy ext of
- SOME flds
- => let val (args,rest) =
- splitargs (map fst (but_last flds)) fargs;
- val more' = mk_ext rest;
- in list_comb (Syntax.const (suffix sfx ext),args@[more'])
- end
- | NONE => raise TERM(msg ^ "no fields defined for "
- ^ ext,[t]))
- | NONE => raise TERM (msg ^ name ^" is no proper field",[t]))
- | mk_ext [] = more
-
- in mk_ext fieldargs end;
-
-fun gen_ext_type_tr sep mark sfx more ctxt t =
- let
- val thy = ProofContext.theory_of ctxt;
- val msg = "error in record-type input: ";
- val fieldargs = dest_ext_fields sep mark t;
- fun splitargs (field::fields) ((name,arg)::fargs) =
- if can (unsuffix name) field
- then let val (args,rest) = splitargs fields fargs
- in (arg::args,rest) end
- else raise TERM (msg ^ "expecting field " ^ field ^ " but got " ^ name, [t])
- | splitargs [] (fargs as (_::_)) = ([],fargs)
- | splitargs (_::_) [] = raise TERM (msg ^ "expecting more fields", [t])
- | splitargs _ _ = ([],[]);
-
- fun mk_ext (fargs as (name,arg)::_) =
- (case get_fieldext thy (Sign.intern_const thy name) of
- SOME (ext,alphas) =>
- (case get_extfields thy ext of
- SOME flds
- => (let
- val flds' = but_last flds;
- val types = map snd flds';
- val (args,rest) = splitargs (map fst flds') fargs;
- val argtypes = map (Sign.certify_typ thy o decode_type thy) args;
- val midx = fold (fn T => fn i => Int.max (maxidx_of_typ T, i))
- argtypes 0;
- val varifyT = varifyT midx;
- val vartypes = map varifyT types;
-
- val subst = fold (Sign.typ_match thy) (vartypes ~~ argtypes)
- Vartab.empty;
- val alphas' = map ((Syntax.term_of_typ (! Syntax.show_sorts)) o
- Envir.norm_type subst o varifyT)
- (but_last alphas);
-
- val more' = mk_ext rest;
- in list_comb (Syntax.const (suffix sfx ext),alphas'@[more'])
- end handle TYPE_MATCH => raise
- TERM (msg ^ "type is no proper record (extension)", [t]))
- | NONE => raise TERM (msg ^ "no fields defined for " ^ ext,[t]))
- | NONE => raise TERM (msg ^ name ^" is no proper field",[t]))
- | mk_ext [] = more
-
- in mk_ext fieldargs end;
-
-fun gen_adv_record_tr sep mark sfx unit ctxt [t] =
- gen_ext_fields_tr sep mark sfx unit ctxt t
- | gen_adv_record_tr _ _ _ _ _ ts = raise TERM ("gen_record_tr", ts);
-
-fun gen_adv_record_scheme_tr sep mark sfx ctxt [t, more] =
- gen_ext_fields_tr sep mark sfx more ctxt t
- | gen_adv_record_scheme_tr _ _ _ _ ts = raise TERM ("gen_record_scheme_tr", ts);
-
-fun gen_adv_record_type_tr sep mark sfx unit ctxt [t] =
- gen_ext_type_tr sep mark sfx unit ctxt t
- | gen_adv_record_type_tr _ _ _ _ _ ts = raise TERM ("gen_record_tr", ts);
-
-fun gen_adv_record_type_scheme_tr sep mark sfx ctxt [t, more] =
- gen_ext_type_tr sep mark sfx more ctxt t
- | gen_adv_record_type_scheme_tr _ _ _ _ ts = raise TERM ("gen_record_scheme_tr", ts);
-
-val adv_record_tr = gen_adv_record_tr "_fields" "_field" extN HOLogic.unit;
-val adv_record_scheme_tr = gen_adv_record_scheme_tr "_fields" "_field" extN;
-
-val adv_record_type_tr =
- gen_adv_record_type_tr "_field_types" "_field_type" ext_typeN
- (Syntax.term_of_typ false (HOLogic.unitT));
-val adv_record_type_scheme_tr =
- gen_adv_record_type_scheme_tr "_field_types" "_field_type" ext_typeN;
-
-
-val parse_translation =
- [("_record_update", record_update_tr),
- ("_update_name", update_name_tr)];
-
-
-val adv_parse_translation =
- [("_record",adv_record_tr),
- ("_record_scheme",adv_record_scheme_tr),
- ("_record_type",adv_record_type_tr),
- ("_record_type_scheme",adv_record_type_scheme_tr)];
-
-
-(* print translations *)
-
-val print_record_type_abbr = ref true;
-val print_record_type_as_fields = ref true;
-
-fun gen_field_upds_tr' mark sfx (tm as Const (name_field, _) $ k $ u) =
- let val t = (case k of (Abs (_,_,(Abs (_,_,t)$Bound 0)))
- => if null (loose_bnos t) then t else raise Match
- | Abs (x,_,t) => if null (loose_bnos t) then t else raise Match
- | _ => raise Match)
-
- (* (case k of (Const ("K_record",_)$t) => t
- | Abs (x,_,Const ("K_record",_)$t$Bound 0) => t
- | _ => raise Match)*)
- in
- (case try (unsuffix sfx) name_field of
- SOME name =>
- apfst (cons (Syntax.const mark $ Syntax.free name $ t)) (gen_field_upds_tr' mark sfx u)
- | NONE => ([], tm))
- end
- | gen_field_upds_tr' _ _ tm = ([], tm);
-
-fun record_update_tr' tm =
- let val (ts, u) = gen_field_upds_tr' "_update" updateN tm in
- if null ts then raise Match
- else Syntax.const "_record_update" $ u $
- foldr1 (fn (v, w) => Syntax.const "_updates" $ v $ w) (rev ts)
- end;
-
-fun gen_field_tr' sfx tr' name =
- let val name_sfx = suffix sfx name
- in (name_sfx, fn [t, u] => tr' (Syntax.const name_sfx $ t $ u) | _ => raise Match) end;
-
-fun record_tr' sep mark record record_scheme unit ctxt t =
- let
- val thy = ProofContext.theory_of ctxt;
- fun field_lst t =
- (case strip_comb t of
- (Const (ext,_),args as (_::_))
- => (case try (unsuffix extN) (Sign.intern_const thy ext) of
- SOME ext'
- => (case get_extfields thy ext' of
- SOME flds
- => (let
- val (f::fs) = but_last (map fst flds);
- val flds' = Sign.extern_const thy f :: map Long_Name.base_name fs;
- val (args',more) = split_last args;
- in (flds'~~args')@field_lst more end
- handle Library.UnequalLengths => [("",t)])
- | NONE => [("",t)])
- | NONE => [("",t)])
- | _ => [("",t)])
-
- val (flds,(_,more)) = split_last (field_lst t);
- val _ = if null flds then raise Match else ();
- val flds' = map (fn (n,t)=>Syntax.const mark$Syntax.const n$t) flds;
- val flds'' = foldr1 (fn (x,y) => Syntax.const sep$x$y) flds';
-
- in if unit more
- then Syntax.const record$flds''
- else Syntax.const record_scheme$flds''$more
- end
-
-fun gen_record_tr' name =
- let val name_sfx = suffix extN name;
- val unit = (fn Const (@{const_syntax "Product_Type.Unity"},_) => true | _ => false);
- fun tr' ctxt ts = record_tr' "_fields" "_field" "_record" "_record_scheme" unit ctxt
- (list_comb (Syntax.const name_sfx,ts))
- in (name_sfx,tr')
- end
-
-fun print_translation names =
- map (gen_field_tr' updateN record_update_tr') names;
-
-
-(* record_type_abbr_tr' tries to reconstruct the record name type abbreviation from *)
-(* the (nested) extension types. *)
-fun record_type_abbr_tr' default_tr' abbr alphas zeta lastExt schemeT ctxt tm =
- let
- val thy = ProofContext.theory_of ctxt;
- (* tm is term representation of a (nested) field type. We first reconstruct the *)
- (* type from tm so that we can continue on the type level rather then the term level.*)
-
- (* WORKAROUND:
- * If a record type occurs in an error message of type inference there
- * may be some internal frees donoted by ??:
- * (Const "_tfree",_)$Free ("??'a",_).
-
- * This will unfortunately be translated to Type ("??'a",[]) instead of
- * TFree ("??'a",_) by typ_of_term, which will confuse unify below.
- * fixT works around.
- *)
- fun fixT (T as Type (x,[])) =
- if String.isPrefix "??'" x then TFree (x,Sign.defaultS thy) else T
- | fixT (Type (x,xs)) = Type (x,map fixT xs)
- | fixT T = T;
-
- val T = fixT (decode_type thy tm);
- val midx = maxidx_of_typ T;
- val varifyT = varifyT midx;
-
- fun mk_type_abbr subst name alphas =
- let val abbrT = Type (name, map (fn a => varifyT (TFree (a, Sign.defaultS thy))) alphas);
- in Syntax.term_of_typ (! Syntax.show_sorts)
- (Sign.extern_typ thy (Envir.norm_type subst abbrT)) end;
-
- fun match rT T = (Sign.typ_match thy (varifyT rT,T)
- Vartab.empty);
-
- in if !print_record_type_abbr
- then (case last_extT T of
- SOME (name,_)
- => if name = lastExt
- then
- (let
- val subst = match schemeT T
- in
- if HOLogic.is_unitT (Envir.norm_type subst (varifyT (TFree(zeta,Sign.defaultS thy))))
- then mk_type_abbr subst abbr alphas
- else mk_type_abbr subst (suffix schemeN abbr) (alphas@[zeta])
- end handle TYPE_MATCH => default_tr' ctxt tm)
- else raise Match (* give print translation of specialised record a chance *)
- | _ => raise Match)
- else default_tr' ctxt tm
- end
-
-fun record_type_tr' sep mark record record_scheme ctxt t =
- let
- val thy = ProofContext.theory_of ctxt;
-
- val T = decode_type thy t;
- val varifyT = varifyT (Term.maxidx_of_typ T);
-
- fun term_of_type T = Syntax.term_of_typ (!Syntax.show_sorts) (Sign.extern_typ thy T);
-
- fun field_lst T =
- (case T of
- Type (ext, args)
- => (case try (unsuffix ext_typeN) ext of
- SOME ext'
- => (case get_extfields thy ext' of
- SOME flds
- => (case get_fieldext thy (fst (hd flds)) of
- SOME (_, alphas)
- => (let
- val (f :: fs) = but_last flds;
- val flds' = apfst (Sign.extern_const thy) f
- :: map (apfst Long_Name.base_name) fs;
- val (args', more) = split_last args;
- val alphavars = map varifyT (but_last alphas);
- val subst = fold2 (curry (Sign.typ_match thy))
- alphavars args' Vartab.empty;
- val flds'' = (map o apsnd)
- (Envir.norm_type subst o varifyT) flds';
- in flds'' @ field_lst more end
- handle TYPE_MATCH => [("", T)]
- | Library.UnequalLengths => [("", T)])
- | NONE => [("", T)])
- | NONE => [("", T)])
- | NONE => [("", T)])
- | _ => [("", T)])
-
- val (flds, (_, moreT)) = split_last (field_lst T);
- val flds' = map (fn (n, T) => Syntax.const mark $ Syntax.const n $ term_of_type T) flds;
- val flds'' = foldr1 (fn (x, y) => Syntax.const sep $ x $ y) flds' handle Empty => raise Match;
-
- in if not (!print_record_type_as_fields) orelse null flds then raise Match
- else if moreT = HOLogic.unitT
- then Syntax.const record$flds''
- else Syntax.const record_scheme$flds''$term_of_type moreT
- end
-
-
-fun gen_record_type_tr' name =
- let val name_sfx = suffix ext_typeN name;
- fun tr' ctxt ts = record_type_tr' "_field_types" "_field_type"
- "_record_type" "_record_type_scheme" ctxt
- (list_comb (Syntax.const name_sfx,ts))
- in (name_sfx,tr')
- end
-
-
-fun gen_record_type_abbr_tr' abbr alphas zeta lastExt schemeT name =
- let val name_sfx = suffix ext_typeN name;
- val default_tr' = record_type_tr' "_field_types" "_field_type"
- "_record_type" "_record_type_scheme"
- fun tr' ctxt ts =
- record_type_abbr_tr' default_tr' abbr alphas zeta lastExt schemeT ctxt
- (list_comb (Syntax.const name_sfx,ts))
- in (name_sfx, tr') end;
-
-(** record simprocs **)
-
-val record_quick_and_dirty_sensitive = ref false;
-
-
-fun quick_and_dirty_prove stndrd thy asms prop tac =
- if !record_quick_and_dirty_sensitive andalso !quick_and_dirty
- then Goal.prove (ProofContext.init thy) [] []
- (Logic.list_implies (map Logic.varify asms,Logic.varify prop))
- (K (SkipProof.cheat_tac @{theory HOL}))
- (* standard can take quite a while for large records, thats why
- * we varify the proposition manually here.*)
- else let val prf = Goal.prove (ProofContext.init thy) [] asms prop tac;
- in if stndrd then standard prf else prf end;
-
-fun quick_and_dirty_prf noopt opt () =
- if !record_quick_and_dirty_sensitive andalso !quick_and_dirty
- then noopt ()
- else opt ();
-
-local
-fun abstract_over_fun_app (Abs (f,fT,t)) =
- let
- val (f',t') = Term.dest_abs (f,fT,t);
- val T = domain_type fT;
- val (x,T') = hd (Term.variant_frees t' [("x",T)]);
- val f_x = Free (f',fT)$(Free (x,T'));
- fun is_constr (Const (c,_)$_) = can (unsuffix extN) c
- | is_constr _ = false;
- fun subst (t as u$w) = if Free (f',fT)=u
- then if is_constr w then f_x
- else raise TERM ("abstract_over_fun_app",[t])
- else subst u$subst w
- | subst (Abs (x,T,t)) = (Abs (x,T,subst t))
- | subst t = t
- val t'' = abstract_over (f_x,subst t');
- val vars = strip_qnt_vars "all" t'';
- val bdy = strip_qnt_body "all" t'';
-
- in list_abs ((x,T')::vars,bdy) end
- | abstract_over_fun_app t = raise TERM ("abstract_over_fun_app",[t]);
-(* Generates a theorem of the kind:
- * !!f x*. PROP P (f ( r x* ) x* == !!r x*. PROP P r x*
- *)
-fun mk_fun_apply_eq (Abs (f, fT, t)) thy =
- let
- val rT = domain_type fT;
- val vars = Term.strip_qnt_vars "all" t;
- val Ts = map snd vars;
- val n = length vars;
- fun app_bounds 0 t = t$Bound 0
- | app_bounds n t = if n > 0 then app_bounds (n-1) (t$Bound n) else t
-
-
- val [P,r] = Term.variant_frees t [("P",rT::Ts--->Term.propT),("r",Ts--->rT)];
- val prop = Logic.mk_equals
- (list_all ((f,fT)::vars,
- app_bounds (n - 1) ((Free P)$(Bound n$app_bounds (n-1) (Free r)))),
- list_all ((fst r,rT)::vars,
- app_bounds (n - 1) ((Free P)$Bound n)));
- val prove_standard = quick_and_dirty_prove true thy;
- val thm = prove_standard [] prop (fn _ =>
- EVERY [rtac equal_intr_rule 1,
- Goal.norm_hhf_tac 1,REPEAT (etac meta_allE 1), atac 1,
- Goal.norm_hhf_tac 1,REPEAT (etac meta_allE 1), atac 1]);
- in thm end
- | mk_fun_apply_eq t thy = raise TERM ("mk_fun_apply_eq",[t]);
-
-in
-(* During proof of theorems produced by record_simproc you can end up in
- * situations like "!!f ... . ... f r ..." where f is an extension update function.
- * In order to split "f r" we transform this to "!!r ... . ... r ..." so that the
- * usual split rules for extensions can apply.
- *)
-val record_split_f_more_simproc =
- Simplifier.simproc @{theory HOL} "record_split_f_more_simp" ["x"]
- (fn thy => fn _ => fn t =>
- (case t of (Const ("all", Type (_, [Type (_, [Type("fun",[T,T']), _]), _])))$
- (trm as Abs _) =>
- (case rec_id (~1) T of
- "" => NONE
- | n => if T=T'
- then (let
- val P=cterm_of thy (abstract_over_fun_app trm);
- val thm = mk_fun_apply_eq trm thy;
- val PV = cterm_of thy (hd (OldTerm.term_vars (prop_of thm)));
- val thm' = cterm_instantiate [(PV,P)] thm;
- in SOME thm' end handle TERM _ => NONE)
- else NONE)
- | _ => NONE))
-end
-
-fun prove_split_simp thy ss T prop =
- let
- val {sel_upd={simpset,...},extsplit,...} = RecordsData.get thy;
- val extsplits =
- Library.foldl (fn (thms,(n,_)) => the_list (Symtab.lookup extsplit n) @ thms)
- ([],dest_recTs T);
- val thms = (case get_splits thy (rec_id (~1) T) of
- SOME (all_thm,_,_,_) =>
- all_thm::(case extsplits of [thm] => [] | _ => extsplits)
- (* [thm] is the same as all_thm *)
- | NONE => extsplits)
- val thms'=K_comp_convs@thms;
- val ss' = (Simplifier.inherit_context ss simpset
- addsimps thms'
- addsimprocs [record_split_f_more_simproc]);
- in
- quick_and_dirty_prove true thy [] prop (fn _ => simp_tac ss' 1)
- end;
-
-
-local
-fun eq (s1:string) (s2:string) = (s1 = s2);
-fun has_field extfields f T =
- exists (fn (eN,_) => exists (eq f o fst) (Symtab.lookup_list extfields eN))
- (dest_recTs T);
-
-fun K_skeleton n (T as Type (_,[_,kT])) (b as Bound i) (Abs (x,xT,t)) =
- if null (loose_bnos t) then ((n,kT),(Abs (x,xT,Bound (i+1)))) else ((n,T),b)
- | K_skeleton n T b _ = ((n,T),b);
-
-(*
-fun K_skeleton n _ b ((K_rec as Const ("Record.K_record",Type (_,[kT,_])))$_) =
- ((n,kT),K_rec$b)
- | K_skeleton n _ (Bound i)
- (Abs (x,T,(K_rec as Const ("Record.K_record",Type (_,[kT,_])))$_$Bound 0)) =
- ((n,kT),Abs (x,T,(K_rec$Bound (i+1)$Bound 0)))
- | K_skeleton n T b _ = ((n,T),b);
- *)
-
-fun normalize_rhs thm =
- let
- val ss = HOL_basic_ss addsimps K_comp_convs;
- val rhs = thm |> Thm.cprop_of |> Thm.dest_comb |> snd;
- val rhs' = (Simplifier.rewrite ss rhs);
- in Thm.transitive thm rhs' end;
-in
-(* record_simproc *)
-(* Simplifies selections of an record update:
- * (1) S (S_update k r) = k (S r)
- * (2) S (X_update k r) = S r
- * The simproc skips multiple updates at once, eg:
- * S (X_update x (Y_update y (S_update k r))) = k (S r)
- * But be careful in (2) because of the extendibility of records.
- * - If S is a more-selector we have to make sure that the update on component
- * X does not affect the selected subrecord.
- * - If X is a more-selector we have to make sure that S is not in the updated
- * subrecord.
- *)
-val record_simproc =
- Simplifier.simproc @{theory HOL} "record_simp" ["x"]
- (fn thy => fn ss => fn t =>
- (case t of (sel as Const (s, Type (_,[domS,rangeS])))$
- ((upd as Const (u,Type(_,[_,Type (_,[rT,_])]))) $ k $ r)=>
- if is_selector thy s then
- (case get_updates thy u of SOME u_name =>
- let
- val {sel_upd={updates,...},extfields,...} = RecordsData.get thy;
-
- fun mk_eq_terms ((upd as Const (u,Type(_,[kT,_]))) $ k $ r) =
- (case Symtab.lookup updates u of
- NONE => NONE
- | SOME u_name
- => if u_name = s
- then (case mk_eq_terms r of
- NONE =>
- let
- val rv = ("r",rT)
- val rb = Bound 0
- val (kv,kb) = K_skeleton "k" kT (Bound 1) k;
- in SOME (upd$kb$rb,kb$(sel$rb),[kv,rv]) end
- | SOME (trm,trm',vars) =>
- let
- val (kv,kb) = K_skeleton "k" kT (Bound (length vars)) k;
- in SOME (upd$kb$trm,kb$trm',kv::vars) end)
- else if has_field extfields u_name rangeS
- orelse has_field extfields s (domain_type kT)
- then NONE
- else (case mk_eq_terms r of
- SOME (trm,trm',vars)
- => let
- val (kv,kb) =
- K_skeleton "k" kT (Bound (length vars)) k;
- in SOME (upd$kb$trm,trm',kv::vars) end
- | NONE
- => let
- val rv = ("r",rT)
- val rb = Bound 0
- val (kv,kb) = K_skeleton "k" kT (Bound 1) k;
- in SOME (upd$kb$rb,sel$rb,[kv,rv]) end))
- | mk_eq_terms r = NONE
- in
- (case mk_eq_terms (upd$k$r) of
- SOME (trm,trm',vars)
- => SOME (prove_split_simp thy ss domS
- (list_all(vars, Logic.mk_equals (sel $ trm, trm'))))
- | NONE => NONE)
- end
- | NONE => NONE)
- else NONE
- | _ => NONE));
-
-(* record_upd_simproc *)
-(* simplify multiple updates:
- * (1) "N_update y (M_update g (N_update x (M_update f r))) =
- (N_update (y o x) (M_update (g o f) r))"
- * (2) "r(|M:= M r|) = r"
- * For (2) special care of "more" updates has to be taken:
- * r(|more := m; A := A r|)
- * If A is contained in the fields of m we cannot remove the update A := A r!
- * (But r(|more := r; A := A (r(|more := r|))|) = r(|more := r|)
-*)
-val record_upd_simproc =
- Simplifier.simproc @{theory HOL} "record_upd_simp" ["x"]
- (fn thy => fn ss => fn t =>
- (case t of ((upd as Const (u, Type(_,[_,Type(_,[rT,_])]))) $ k $ r) =>
- let datatype ('a,'b) calc = Init of 'b | Inter of 'a
- val {sel_upd={selectors,updates,...},extfields,...} = RecordsData.get thy;
-
- (*fun mk_abs_var x t = (x, fastype_of t);*)
- fun sel_name u = Long_Name.base_name (unsuffix updateN u);
-
- fun seed s (upd as Const (more,Type(_,[mT,_]))$ k $ r) =
- if has_field extfields s (domain_type' mT) then upd else seed s r
- | seed _ r = r;
-
- fun grow u uT k kT vars (sprout,skeleton) =
- if sel_name u = moreN
- then let val (kv,kb) = K_skeleton "k" kT (Bound (length vars)) k;
- in ((Const (u,uT)$k$sprout,Const (u,uT)$kb$skeleton),kv::vars) end
- else ((sprout,skeleton),vars);
-
-
- fun dest_k (Abs (x,T,((sel as Const (s,_))$r))) =
- if null (loose_bnos r) then SOME (x,T,sel,s,r) else NONE
- | dest_k (Abs (_,_,(Abs (x,T,((sel as Const (s,_))$r)))$Bound 0)) =
- (* eta expanded variant *)
- if null (loose_bnos r) then SOME (x,T,sel,s,r) else NONE
- | dest_k _ = NONE;
-
- fun is_upd_same (sprout,skeleton) u k =
- (case dest_k k of SOME (x,T,sel,s,r) =>
- if (unsuffix updateN u) = s andalso (seed s sprout) = r
- then SOME (fn t => Abs (x,T,incr_boundvars 1 t),sel,seed s skeleton)
- else NONE
- | NONE => NONE);
-
- fun init_seed r = ((r,Bound 0), [("r", rT)]);
-
- fun add (n:string) f fmaps =
- (case AList.lookup (op =) fmaps n of
- NONE => AList.update (op =) (n,[f]) fmaps
- | SOME fs => AList.update (op =) (n,f::fs) fmaps)
-
- fun comps (n:string) T fmaps =
- (case AList.lookup (op =) fmaps n of
- SOME fs =>
- foldr1 (fn (f,g) => Const ("Fun.comp",(T-->T)-->(T-->T)-->(T-->T))$f$g) fs
- | NONE => error ("record_upd_simproc.comps"))
-
- (* mk_updterm returns either
- * - Init (orig-term, orig-term-skeleton, vars) if no optimisation can be made,
- * where vars are the bound variables in the skeleton
- * - Inter (orig-term-skeleton,simplified-term-skeleton,
- * vars, (term-sprout, skeleton-sprout))
- * where "All vars. orig-term-skeleton = simplified-term-skeleton" is
- * the desired simplification rule,
- * the sprouts accumulate the "more-updates" on the way from the seed
- * to the outermost update. It is only relevant to calculate the
- * possible simplification for (2)
- * The algorithm first walks down the updates to the seed-record while
- * memorising the updates in the already-table. While walking up the
- * updates again, the optimised term is constructed.
- *)
- fun mk_updterm upds already
- (t as ((upd as Const (u,uT as (Type (_,[kT,_])))) $ k $ r)) =
- if Symtab.defined upds u
- then let
- fun rest already = mk_updterm upds already
- in if u mem_string already
- then (case (rest already r) of
- Init ((sprout,skel),vars) =>
- let
- val n = sel_name u;
- val (kv,kb) = K_skeleton n kT (Bound (length vars)) k;
- val (sprout',vars')= grow u uT k kT (kv::vars) (sprout,skel);
- in Inter (upd$kb$skel,skel,vars',add n kb [],sprout') end
- | Inter (trm,trm',vars,fmaps,sprout) =>
- let
- val n = sel_name u;
- val (kv,kb) = K_skeleton n kT (Bound (length vars)) k;
- val (sprout',vars') = grow u uT k kT (kv::vars) sprout;
- in Inter(upd$kb$trm,trm',kv::vars',add n kb fmaps,sprout')
- end)
- else
- (case rest (u::already) r of
- Init ((sprout,skel),vars) =>
- (case is_upd_same (sprout,skel) u k of
- SOME (K_rec,sel,skel') =>
- let
- val (sprout',vars') = grow u uT k kT vars (sprout,skel);
- in Inter(upd$(K_rec (sel$skel'))$skel,skel,vars',[],sprout')
- end
- | NONE =>
- let
- val n = sel_name u;
- val (kv,kb) = K_skeleton n kT (Bound (length vars)) k;
- in Init ((upd$k$sprout,upd$kb$skel),kv::vars) end)
- | Inter (trm,trm',vars,fmaps,sprout) =>
- (case is_upd_same sprout u k of
- SOME (K_rec,sel,skel) =>
- let
- val (sprout',vars') = grow u uT k kT vars sprout
- in Inter(upd$(K_rec (sel$skel))$trm,trm',vars',fmaps,sprout')
- end
- | NONE =>
- let
- val n = sel_name u
- val T = domain_type kT
- val (kv,kb) = K_skeleton n kT (Bound (length vars)) k;
- val (sprout',vars') = grow u uT k kT (kv::vars) sprout
- val fmaps' = add n kb fmaps
- in Inter (upd$kb$trm,upd$comps n T fmaps'$trm'
- ,vars',fmaps',sprout') end))
- end
- else Init (init_seed t)
- | mk_updterm _ _ t = Init (init_seed t);
-
- in (case mk_updterm updates [] t of
- Inter (trm,trm',vars,_,_)
- => SOME (normalize_rhs
- (prove_split_simp thy ss rT
- (list_all(vars, Logic.mk_equals (trm, trm')))))
- | _ => NONE)
- end
- | _ => NONE))
-end
-
-(* record_eq_simproc *)
-(* looks up the most specific record-equality.
- * Note on efficiency:
- * Testing equality of records boils down to the test of equality of all components.
- * Therefore the complexity is: #components * complexity for single component.
- * Especially if a record has a lot of components it may be better to split up
- * the record first and do simplification on that (record_split_simp_tac).
- * e.g. r(|lots of updates|) = x
- *
- * record_eq_simproc record_split_simp_tac
- * Complexity: #components * #updates #updates
- *
- *)
-val record_eq_simproc =
- Simplifier.simproc @{theory HOL} "record_eq_simp" ["r = s"]
- (fn thy => fn _ => fn t =>
- (case t of Const ("op =", Type (_, [T, _])) $ _ $ _ =>
- (case rec_id (~1) T of
- "" => NONE
- | name => (case get_equalities thy name of
- NONE => NONE
- | SOME thm => SOME (thm RS Eq_TrueI)))
- | _ => NONE));
-
-(* record_split_simproc *)
-(* splits quantified occurrences of records, for which P holds. P can peek on the
- * subterm starting at the quantified occurrence of the record (including the quantifier)
- * P t = 0: do not split
- * P t = ~1: completely split
- * P t > 0: split up to given bound of record extensions
- *)
-fun record_split_simproc P =
- Simplifier.simproc @{theory HOL} "record_split_simp" ["x"]
- (fn thy => fn _ => fn t =>
- (case t of (Const (quantifier, Type (_, [Type (_, [T, _]), _])))$trm =>
- if quantifier = "All" orelse quantifier = "all" orelse quantifier = "Ex"
- then (case rec_id (~1) T of
- "" => NONE
- | name
- => let val split = P t
- in if split <> 0 then
- (case get_splits thy (rec_id split T) of
- NONE => NONE
- | SOME (all_thm, All_thm, Ex_thm,_)
- => SOME (case quantifier of
- "all" => all_thm
- | "All" => All_thm RS eq_reflection
- | "Ex" => Ex_thm RS eq_reflection
- | _ => error "record_split_simproc"))
- else NONE
- end)
- else NONE
- | _ => NONE))
-
-val record_ex_sel_eq_simproc =
- Simplifier.simproc @{theory HOL} "record_ex_sel_eq_simproc" ["Ex t"]
- (fn thy => fn ss => fn t =>
- let
- fun prove prop =
- quick_and_dirty_prove true thy [] prop
- (fn _ => simp_tac (Simplifier.inherit_context ss (get_simpset thy)
- addsimps simp_thms addsimprocs [record_split_simproc (K ~1)]) 1);
-
- fun mkeq (lr,Teq,(sel,Tsel),x) i =
- if is_selector thy sel then
- let val x' = if not (loose_bvar1 (x,0))
- then Free ("x" ^ string_of_int i, range_type Tsel)
- else raise TERM ("",[x]);
- val sel' = Const (sel,Tsel)$Bound 0;
- val (l,r) = if lr then (sel',x') else (x',sel');
- in Const ("op =",Teq)$l$r end
- else raise TERM ("",[Const (sel,Tsel)]);
-
- fun dest_sel_eq (Const ("op =",Teq)$(Const (sel,Tsel)$Bound 0)$X) =
- (true,Teq,(sel,Tsel),X)
- | dest_sel_eq (Const ("op =",Teq)$X$(Const (sel,Tsel)$Bound 0)) =
- (false,Teq,(sel,Tsel),X)
- | dest_sel_eq _ = raise TERM ("",[]);
-
- in
- (case t of
- (Const ("Ex",Tex)$Abs(s,T,t)) =>
- (let val eq = mkeq (dest_sel_eq t) 0;
- val prop = list_all ([("r",T)],
- Logic.mk_equals (Const ("Ex",Tex)$Abs(s,T,eq),
- HOLogic.true_const));
- in SOME (prove prop) end
- handle TERM _ => NONE)
- | _ => NONE)
- end)
-
-
-
-
-local
-val inductive_atomize = thms "induct_atomize";
-val inductive_rulify = thms "induct_rulify";
-in
-(* record_split_simp_tac *)
-(* splits (and simplifies) all records in the goal for which P holds.
- * For quantified occurrences of a record
- * P can peek on the whole subterm (including the quantifier); for free variables P
- * can only peek on the variable itself.
- * P t = 0: do not split
- * P t = ~1: completely split
- * P t > 0: split up to given bound of record extensions
- *)
-fun record_split_simp_tac thms P i st =
- let
- val thy = Thm.theory_of_thm st;
-
- val has_rec = exists_Const
- (fn (s, Type (_, [Type (_, [T, _]), _])) =>
- (s = "all" orelse s = "All" orelse s = "Ex") andalso is_recT T
- | _ => false);
-
- val goal = nth (Thm.prems_of st) (i - 1);
- val frees = List.filter (is_recT o type_of) (OldTerm.term_frees goal);
-
- fun mk_split_free_tac free induct_thm i =
- let val cfree = cterm_of thy free;
- val (_$(_$r)) = concl_of induct_thm;
- val crec = cterm_of thy r;
- val thm = cterm_instantiate [(crec,cfree)] induct_thm;
- in EVERY [simp_tac (HOL_basic_ss addsimps inductive_atomize) i,
- rtac thm i,
- simp_tac (HOL_basic_ss addsimps inductive_rulify) i]
- end;
-
- fun split_free_tac P i (free as Free (n,T)) =
- (case rec_id (~1) T of
- "" => NONE
- | name => let val split = P free
- in if split <> 0 then
- (case get_splits thy (rec_id split T) of
- NONE => NONE
- | SOME (_,_,_,induct_thm)
- => SOME (mk_split_free_tac free induct_thm i))
- else NONE
- end)
- | split_free_tac _ _ _ = NONE;
-
- val split_frees_tacs = List.mapPartial (split_free_tac P i) frees;
-
- val simprocs = if has_rec goal then [record_split_simproc P] else [];
- val thms' = K_comp_convs@thms
- in st |> ((EVERY split_frees_tacs)
- THEN (Simplifier.full_simp_tac (get_simpset thy addsimps thms' addsimprocs simprocs) i))
- end handle Empty => Seq.empty;
-end;
-
-
-(* record_split_tac *)
-(* splits all records in the goal, which are quantified by ! or !!. *)
-fun record_split_tac i st =
- let
- val thy = Thm.theory_of_thm st;
-
- val has_rec = exists_Const
- (fn (s, Type (_, [Type (_, [T, _]), _])) =>
- (s = "all" orelse s = "All") andalso is_recT T
- | _ => false);
-
- val goal = nth (Thm.prems_of st) (i - 1);
-
- fun is_all t =
- (case t of (Const (quantifier, _)$_) =>
- if quantifier = "All" orelse quantifier = "all" then ~1 else 0
- | _ => 0);
-
- in if has_rec goal
- then Simplifier.full_simp_tac
- (HOL_basic_ss addsimprocs [record_split_simproc is_all]) i st
- else Seq.empty
- end handle Subscript => Seq.empty;
-
-(* wrapper *)
-
-val record_split_name = "record_split_tac";
-val record_split_wrapper = (record_split_name, fn tac => record_split_tac ORELSE' tac);
-
-
-
-(** theory extender interface **)
-
-(* prepare arguments *)
-
-fun read_raw_parent ctxt raw_T =
- (case ProofContext.read_typ_abbrev ctxt raw_T of
- Type (name, Ts) => (Ts, name)
- | T => error ("Bad parent record specification: " ^ Syntax.string_of_typ ctxt T));
-
-fun read_typ ctxt raw_T env =
- let
- val ctxt' = fold (Variable.declare_typ o TFree) env ctxt;
- val T = Syntax.read_typ ctxt' raw_T;
- val env' = OldTerm.add_typ_tfrees (T, env);
- in (T, env') end;
-
-fun cert_typ ctxt raw_T env =
- let
- val thy = ProofContext.theory_of ctxt;
- val T = Type.no_tvars (Sign.certify_typ thy raw_T) handle TYPE (msg, _, _) => error msg;
- val env' = OldTerm.add_typ_tfrees (T, env);
- in (T, env') end;
-
-
-(* attributes *)
-
-fun case_names_fields x = RuleCases.case_names ["fields"] x;
-fun induct_type_global name = [case_names_fields, Induct.induct_type name];
-fun cases_type_global name = [case_names_fields, Induct.cases_type name];
-
-(* tactics *)
-
-fun simp_all_tac ss simps = ALLGOALS (Simplifier.asm_full_simp_tac (ss addsimps simps));
-
-(* do case analysis / induction according to rule on last parameter of ith subgoal
- * (or on s if there are no parameters);
- * Instatiation of record variable (and predicate) in rule is calculated to
- * avoid problems with higher order unification.
- *)
-
-fun try_param_tac s rule i st =
- let
- val cert = cterm_of (Thm.theory_of_thm st);
- val g = nth (prems_of st) (i - 1);
- val params = Logic.strip_params g;
- val concl = HOLogic.dest_Trueprop (Logic.strip_assums_concl g);
- val rule' = Thm.lift_rule (Thm.cprem_of st i) rule;
- val (P, ys) = strip_comb (HOLogic.dest_Trueprop
- (Logic.strip_assums_concl (prop_of rule')));
- (* ca indicates if rule is a case analysis or induction rule *)
- val (x, ca) = (case rev (Library.drop (length params, ys)) of
- [] => (head_of (fst (HOLogic.dest_eq (HOLogic.dest_Trueprop
- (hd (rev (Logic.strip_assums_hyp (hd (prems_of rule')))))))), true)
- | [x] => (head_of x, false));
- val rule'' = cterm_instantiate (map (pairself cert) (case (rev params) of
- [] => (case AList.lookup (op =) (map dest_Free (OldTerm.term_frees (prop_of st))) s of
- NONE => sys_error "try_param_tac: no such variable"
- | SOME T => [(P, if ca then concl else lambda (Free (s, T)) concl),
- (x, Free (s, T))])
- | (_, T) :: _ => [(P, list_abs (params, if ca then concl
- else incr_boundvars 1 (Abs (s, T, concl)))),
- (x, list_abs (params, Bound 0))])) rule'
- in compose_tac (false, rule'', nprems_of rule) i st end;
-
-
-(* !!x1 ... xn. ... ==> EX x1 ... xn. P x1 ... xn;
- instantiates x1 ... xn with parameters x1 ... xn *)
-fun ex_inst_tac i st =
- let
- val thy = Thm.theory_of_thm st;
- val g = nth (prems_of st) (i - 1);
- val params = Logic.strip_params g;
- val exI' = Thm.lift_rule (Thm.cprem_of st i) exI;
- val (_$(_$x)) = Logic.strip_assums_concl (hd (prems_of exI'));
- val cx = cterm_of thy (fst (strip_comb x));
-
- in Seq.single (Library.foldl (fn (st,v) =>
- Seq.hd
- (compose_tac (false, cterm_instantiate
- [(cx,cterm_of thy (list_abs (params,Bound v)))] exI',1)
- i st)) (st,((length params) - 1) downto 0))
- end;
-
-fun extension_typedef name repT alphas thy =
- let
- fun get_thms thy name =
- let
- val SOME { Abs_induct = abs_induct,
- Abs_inject=abs_inject, Abs_inverse = abs_inverse, ...} = TypedefPackage.get_info thy name;
- val rewrite_rule = MetaSimplifier.rewrite_rule [rec_UNIV_I, rec_True_simp];
- in map rewrite_rule [abs_inject, abs_inverse, abs_induct] end;
- val tname = Binding.name (Long_Name.base_name name);
- in
- thy
- |> TypecopyPackage.typecopy (Binding.suffix_name ext_typeN tname, alphas) repT NONE
- |-> (fn (name, _) => `(fn thy => get_thms thy name))
- end;
-
-fun mixit convs refls =
- let fun f ((res,lhs,rhs),refl) = ((refl,List.revAppend (lhs,refl::tl rhs))::res,hd rhs::lhs,tl rhs);
- in #1 (Library.foldl f (([],[],convs),refls)) end;
-
-
-fun extension_definition full name fields names alphas zeta moreT more vars thy =
- let
- val base = Long_Name.base_name;
- val fieldTs = (map snd fields);
- val alphas_zeta = alphas@[zeta];
- val alphas_zetaTs = map (fn n => TFree (n, HOLogic.typeS)) alphas_zeta;
- val vT = TFree (Name.variant alphas_zeta "'v", HOLogic.typeS);
- val extT_name = suffix ext_typeN name
- val extT = Type (extT_name, alphas_zetaTs);
- val repT = foldr1 HOLogic.mk_prodT (fieldTs@[moreT]);
- val fields_more = fields@[(full moreN,moreT)];
- val fields_moreTs = fieldTs@[moreT];
- val bfields_more = map (apfst base) fields_more;
- val r = Free (rN,extT)
- val len = length fields;
- val idxms = 0 upto len;
-
- (* prepare declarations and definitions *)
-
- (*fields constructor*)
- val ext_decl = (mk_extC (name,extT) fields_moreTs);
- (*
- val ext_spec = Const ext_decl :==
- (foldr (uncurry lambda)
- (mk_Abs name repT extT $ (foldr1 HOLogic.mk_prod (vars@[more]))) (vars@[more]))
- *)
- val ext_spec = list_comb (Const ext_decl,vars@[more]) :==
- (mk_Abs name repT extT $ (foldr1 HOLogic.mk_prod (vars@[more])));
-
- fun mk_ext args = list_comb (Const ext_decl, args);
-
- (*destructors*)
- val _ = timing_msg "record extension preparing definitions";
- val dest_decls = map (mk_selC extT o (apfst (suffix ext_dest))) bfields_more;
-
- fun mk_dest_spec (i, (c,T)) =
- let val snds = (funpow i HOLogic.mk_snd (mk_Rep name repT extT $ r))
- in Const (mk_selC extT (suffix ext_dest c,T))
- :== (lambda r (if i=len then snds else HOLogic.mk_fst snds))
- end;
- val dest_specs =
- ListPair.map mk_dest_spec (idxms, fields_more);
-
- (*updates*)
- val upd_decls = map (mk_updC updN extT) bfields_more;
- fun mk_upd_spec (c,T) =
- let
- val args = map (fn (n,nT) => if n=c then Free (base c,T --> T)$
- (mk_sel r (suffix ext_dest n,nT))
- else (mk_sel r (suffix ext_dest n,nT)))
- fields_more;
- in Const (mk_updC updN extT (c,T))$(Free (base c,T --> T))$r
- :== mk_ext args
- end;
- val upd_specs = map mk_upd_spec fields_more;
-
- (* 1st stage: defs_thy *)
- fun mk_defs () =
- thy
- |> extension_typedef name repT (alphas @ [zeta])
- ||> Sign.add_consts_i
- (map (Syntax.no_syn o apfst Binding.name) (apfst base ext_decl :: dest_decls @ upd_decls))
- ||>> PureThy.add_defs false
- (map (Thm.no_attributes o apfst Binding.name) (ext_spec :: dest_specs))
- ||>> PureThy.add_defs false
- (map (Thm.no_attributes o apfst Binding.name) upd_specs)
- |-> (fn args as ((_, dest_defs), upd_defs) =>
- fold Code.add_default_eqn dest_defs
- #> fold Code.add_default_eqn upd_defs
- #> pair args);
- val ((([abs_inject, abs_inverse, abs_induct], ext_def :: dest_defs), upd_defs), defs_thy) =
- timeit_msg "record extension type/selector/update defs:" mk_defs;
-
- (* prepare propositions *)
- val _ = timing_msg "record extension preparing propositions";
- val vars_more = vars@[more];
- val named_vars_more = (names@[full moreN])~~vars_more;
- val variants = map (fn (Free (x,_))=>x) vars_more;
- val ext = mk_ext vars_more;
- val s = Free (rN, extT);
- val w = Free (wN, extT);
- val P = Free (Name.variant variants "P", extT-->HOLogic.boolT);
- val C = Free (Name.variant variants "C", HOLogic.boolT);
-
- val inject_prop =
- let val vars_more' = map (fn (Free (x,T)) => Free (x ^ "'",T)) vars_more;
- in All (map dest_Free (vars_more@vars_more'))
- ((HOLogic.eq_const extT $
- mk_ext vars_more$mk_ext vars_more')
- ===
- foldr1 HOLogic.mk_conj (map HOLogic.mk_eq (vars_more ~~ vars_more')))
- end;
-
- val induct_prop =
- (All (map dest_Free vars_more) (Trueprop (P $ ext)), Trueprop (P $ s));
-
- val cases_prop =
- (All (map dest_Free vars_more)
- (Trueprop (HOLogic.mk_eq (s,ext)) ==> Trueprop C))
- ==> Trueprop C;
-
- (*destructors*)
- val dest_conv_props =
- map (fn (c, x as Free (_,T)) => mk_sel ext (suffix ext_dest c,T) === x) named_vars_more;
-
- (*updates*)
- fun mk_upd_prop (i,(c,T)) =
- let val x' = Free (Name.variant variants (base c ^ "'"),T --> T)
- val args' = nth_map i (K (x'$nth vars_more i)) vars_more
- in mk_upd updN c x' ext === mk_ext args' end;
- val upd_conv_props = ListPair.map mk_upd_prop (idxms, fields_more);
-
- val surjective_prop =
- let val args =
- map (fn (c, Free (_,T)) => mk_sel s (suffix ext_dest c,T)) named_vars_more;
- in s === mk_ext args end;
-
- val split_meta_prop =
- let val P = Free (Name.variant variants "P", extT-->Term.propT) in
- Logic.mk_equals
- (All [dest_Free s] (P $ s), All (map dest_Free vars_more) (P $ ext))
- end;
-
- fun prove stndrd = quick_and_dirty_prove stndrd defs_thy;
- val prove_standard = quick_and_dirty_prove true defs_thy;
- fun prove_simp stndrd simps =
- let val tac = simp_all_tac HOL_ss simps
- in fn prop => prove stndrd [] prop (K tac) end;
-
- fun inject_prf () = (prove_simp true [ext_def,abs_inject,Pair_eq] inject_prop);
- val inject = timeit_msg "record extension inject proof:" inject_prf;
-
- fun induct_prf () =
- let val (assm, concl) = induct_prop
- in prove_standard [assm] concl (fn {prems, ...} =>
- EVERY [try_param_tac rN abs_induct 1,
- simp_tac (HOL_ss addsimps [split_paired_all]) 1,
- resolve_tac (map (rewrite_rule [ext_def]) prems) 1])
- end;
- val induct = timeit_msg "record extension induct proof:" induct_prf;
-
- fun cases_prf_opt () =
- let
- val (_$(Pvar$_)) = concl_of induct;
- val ind = cterm_instantiate
- [(cterm_of defs_thy Pvar, cterm_of defs_thy
- (lambda w (HOLogic.imp$HOLogic.mk_eq(r,w)$C)))]
- induct;
- in standard (ObjectLogic.rulify (mp OF [ind, refl])) end;
-
- fun cases_prf_noopt () =
- prove_standard [] cases_prop (fn _ =>
- EVERY [asm_full_simp_tac (HOL_basic_ss addsimps [atomize_all, atomize_imp]) 1,
- try_param_tac rN induct 1,
- rtac impI 1,
- REPEAT (etac allE 1),
- etac mp 1,
- rtac refl 1])
-
- val cases_prf = quick_and_dirty_prf cases_prf_noopt cases_prf_opt;
- val cases = timeit_msg "record extension cases proof:" cases_prf;
-
- fun dest_convs_prf () = map (prove_simp false
- ([ext_def,abs_inverse]@Pair_sel_convs@dest_defs)) dest_conv_props;
- val dest_convs = timeit_msg "record extension dest_convs proof:" dest_convs_prf;
- fun dest_convs_standard_prf () = map standard dest_convs;
-
- val dest_convs_standard =
- timeit_msg "record extension dest_convs_standard proof:" dest_convs_standard_prf;
-
- fun upd_convs_prf_noopt () = map (prove_simp true (dest_convs_standard@upd_defs))
- upd_conv_props;
- fun upd_convs_prf_opt () =
- let
-
- fun mkrefl (c,T) = Thm.reflexive
- (cterm_of defs_thy (Free (Name.variant variants (base c ^ "'"),T-->T)));
- val refls = map mkrefl fields_more;
- val dest_convs' = map mk_meta_eq dest_convs;
- val map_eqs = map (uncurry Thm.combination) (refls ~~ dest_convs');
-
- val constr_refl = Thm.reflexive (cterm_of defs_thy (head_of ext));
-
- fun mkthm (udef,(fld_refl,thms)) =
- let val bdyeq = Library.foldl (uncurry Thm.combination) (constr_refl,thms);
- (* (|N=N (|N=N,M=M,K=K,more=more|)
- M=M (|N=N,M=M,K=K,more=more|)
- K=K'
- more = more (|N=N,M=M,K=K,more=more|) =
- (|N=N,M=M,K=K',more=more|)
- *)
- val (_$(_$v$r)$_) = prop_of udef;
- val (_$(v'$_)$_) = prop_of fld_refl;
- val udef' = cterm_instantiate
- [(cterm_of defs_thy v,cterm_of defs_thy v'),
- (cterm_of defs_thy r,cterm_of defs_thy ext)] udef;
- in standard (Thm.transitive udef' bdyeq) end;
- in map mkthm (rev upd_defs ~~ (mixit dest_convs' map_eqs)) end;
-
- val upd_convs_prf = quick_and_dirty_prf upd_convs_prf_noopt upd_convs_prf_opt;
-
- val upd_convs =
- timeit_msg "record extension upd_convs proof:" upd_convs_prf;
-
- fun surjective_prf () =
- prove_standard [] surjective_prop (fn _ =>
- (EVERY [try_param_tac rN induct 1,
- simp_tac (HOL_basic_ss addsimps dest_convs_standard) 1]));
- val surjective = timeit_msg "record extension surjective proof:" surjective_prf;
-
- fun split_meta_prf () =
- prove_standard [] split_meta_prop (fn _ =>
- EVERY [rtac equal_intr_rule 1, Goal.norm_hhf_tac 1,
- etac meta_allE 1, atac 1,
- rtac (prop_subst OF [surjective]) 1,
- REPEAT (etac meta_allE 1), atac 1]);
- val split_meta = timeit_msg "record extension split_meta proof:" split_meta_prf;
-
-
- val (([inject',induct',cases',surjective',split_meta'],
- [dest_convs',upd_convs']),
- thm_thy) =
- defs_thy
- |> (PureThy.add_thms o map (Thm.no_attributes o apfst Binding.name))
- [("ext_inject", inject),
- ("ext_induct", induct),
- ("ext_cases", cases),
- ("ext_surjective", surjective),
- ("ext_split", split_meta)]
- ||>> (PureThy.add_thmss o map (Thm.no_attributes o apfst Binding.name))
- [("dest_convs", dest_convs_standard), ("upd_convs", upd_convs)]
-
- in (thm_thy,extT,induct',inject',dest_convs',split_meta',upd_convs')
- end;
-
-fun chunks [] [] = []
- | chunks [] xs = [xs]
- | chunks (l::ls) xs = Library.take (l,xs)::chunks ls (Library.drop (l,xs));
-
-fun chop_last [] = error "last: list should not be empty"
- | chop_last [x] = ([],x)
- | chop_last (x::xs) = let val (tl,l) = chop_last xs in (x::tl,l) end;
-
-fun subst_last s [] = error "subst_last: list should not be empty"
- | subst_last s ([x]) = [s]
- | subst_last s (x::xs) = (x::subst_last s xs);
-
-(* mk_recordT builds up the record type from the current extension tpye extT and a list
- * of parent extensions, starting with the root of the record hierarchy
-*)
-fun mk_recordT extT =
- fold_rev (fn (parent, Ts) => fn T => Type (parent, subst_last T Ts)) extT;
-
-
-
-fun obj_to_meta_all thm =
- let
- fun E thm = case (SOME (spec OF [thm]) handle THM _ => NONE) of
- SOME thm' => E thm'
- | NONE => thm;
- val th1 = E thm;
- val th2 = Drule.forall_intr_vars th1;
- in th2 end;
-
-fun meta_to_obj_all thm =
- let
- val thy = Thm.theory_of_thm thm;
- val prop = Thm.prop_of thm;
- val params = Logic.strip_params prop;
- val concl = HOLogic.dest_Trueprop (Logic.strip_assums_concl prop);
- val ct = cterm_of thy
- (HOLogic.mk_Trueprop (HOLogic.list_all (params, concl)));
- val thm' = Seq.hd (REPEAT (rtac allI 1) (Thm.trivial ct));
- in
- Thm.implies_elim thm' thm
- end;
-
-
-
-(* record_definition *)
-
-fun record_definition (args, bname) parent (parents: parent_info list) raw_fields thy =
- let
- val external_names = NameSpace.external_names (Sign.naming_of thy);
-
- val alphas = map fst args;
- val name = Sign.full_bname thy bname;
- val full = Sign.full_bname_path thy bname;
- val base = Long_Name.base_name;
-
- val (bfields, field_syntax) = split_list (map (fn (x, T, mx) => ((x, T), mx)) raw_fields);
-
- val parent_fields = List.concat (map #fields parents);
- val parent_chunks = map (length o #fields) parents;
- val parent_names = map fst parent_fields;
- val parent_types = map snd parent_fields;
- val parent_fields_len = length parent_fields;
- val parent_variants = Name.variant_list [moreN, rN, rN ^ "'", wN] (map base parent_names);
- val parent_vars = ListPair.map Free (parent_variants, parent_types);
- val parent_len = length parents;
- val parents_idx = (map #name parents) ~~ (0 upto (parent_len - 1));
-
- val fields = map (apfst full) bfields;
- val names = map fst fields;
- val extN = full bname;
- val types = map snd fields;
- val alphas_fields = List.foldr OldTerm.add_typ_tfree_names [] types;
- val alphas_ext = alphas inter alphas_fields;
- val len = length fields;
- val variants =
- Name.variant_list (moreN :: rN :: (rN ^ "'") :: wN :: parent_variants) (map fst bfields);
- val vars = ListPair.map Free (variants, types);
- val named_vars = names ~~ vars;
- val idxs = 0 upto (len - 1);
- val idxms = 0 upto len;
-
- val all_fields = parent_fields @ fields;
- val all_names = parent_names @ names;
- val all_types = parent_types @ types;
- val all_len = parent_fields_len + len;
- val all_variants = parent_variants @ variants;
- val all_vars = parent_vars @ vars;
- val all_named_vars = (parent_names ~~ parent_vars) @ named_vars;
-
-
- val zeta = Name.variant alphas "'z";
- val moreT = TFree (zeta, HOLogic.typeS);
- val more = Free (moreN, moreT);
- val full_moreN = full moreN;
- val bfields_more = bfields @ [(moreN,moreT)];
- val fields_more = fields @ [(full_moreN,moreT)];
- val vars_more = vars @ [more];
- val named_vars_more = named_vars @[(full_moreN,more)];
- val all_vars_more = all_vars @ [more];
- val all_named_vars_more = all_named_vars @ [(full_moreN,more)];
-
- (* 1st stage: extension_thy *)
- val (extension_thy,extT,ext_induct,ext_inject,ext_dest_convs,ext_split,u_convs) =
- thy
- |> Sign.add_path bname
- |> extension_definition full extN fields names alphas_ext zeta moreT more vars;
-
- val _ = timing_msg "record preparing definitions";
- val Type extension_scheme = extT;
- val extension_name = unsuffix ext_typeN (fst extension_scheme);
- val extension = let val (n,Ts) = extension_scheme in (n,subst_last HOLogic.unitT Ts) end;
- val extension_names =
- (map ((unsuffix ext_typeN) o fst o #extension) parents) @ [extN];
- val extension_id = Library.foldl (op ^) ("",extension_names);
-
-
- fun rec_schemeT n = mk_recordT (map #extension (prune n parents)) extT;
- val rec_schemeT0 = rec_schemeT 0;
-
- fun recT n =
- let val (c,Ts) = extension
- in mk_recordT (map #extension (prune n parents)) (Type (c,subst_last HOLogic.unitT Ts))
- end;
- val recT0 = recT 0;
-
- fun mk_rec args n =
- let val (args',more) = chop_last args;
- fun mk_ext' (((name,T),args),more) = mk_ext (name,T) (args@[more]);
- fun build Ts =
- List.foldr mk_ext' more (prune n (extension_names ~~ Ts ~~ (chunks parent_chunks args')))
- in
- if more = HOLogic.unit
- then build (map recT (0 upto parent_len))
- else build (map rec_schemeT (0 upto parent_len))
- end;
-
- val r_rec0 = mk_rec all_vars_more 0;
- val r_rec_unit0 = mk_rec (all_vars@[HOLogic.unit]) 0;
-
- fun r n = Free (rN, rec_schemeT n)
- val r0 = r 0;
- fun r_unit n = Free (rN, recT n)
- val r_unit0 = r_unit 0;
- val w = Free (wN, rec_schemeT 0)
-
- (* prepare print translation functions *)
- val field_tr's =
- print_translation (distinct (op =) (maps external_names (full_moreN :: names)));
-
- val adv_ext_tr's =
- let
- val trnames = external_names extN;
- in map (gen_record_tr') trnames end;
-
- val adv_record_type_abbr_tr's =
- let val trnames = external_names (hd extension_names);
- val lastExt = unsuffix ext_typeN (fst extension);
- in map (gen_record_type_abbr_tr' name alphas zeta lastExt rec_schemeT0) trnames
- end;
-
- val adv_record_type_tr's =
- let val trnames = if parent_len > 0 then external_names extN else [];
- (* avoid conflict with adv_record_type_abbr_tr's *)
- in map (gen_record_type_tr') trnames
- end;
-
-
- (* prepare declarations *)
-
- val sel_decls = map (mk_selC rec_schemeT0) bfields_more;
- val upd_decls = map (mk_updC updateN rec_schemeT0) bfields_more;
- val make_decl = (makeN, all_types ---> recT0);
- val fields_decl = (fields_selN, types ---> Type extension);
- val extend_decl = (extendN, recT0 --> moreT --> rec_schemeT0);
- val truncate_decl = (truncateN, rec_schemeT0 --> recT0);
-
- (* prepare definitions *)
-
- fun parent_more s =
- if null parents then s
- else mk_sel s (Long_Name.qualify (#name (List.last parents)) moreN, extT);
-
- fun parent_more_upd v s =
- if null parents then v$s
- else let val mp = Long_Name.qualify (#name (List.last parents)) moreN;
- in mk_upd updateN mp v s end;
-
- (*record (scheme) type abbreviation*)
- val recordT_specs =
- [(Binding.name (suffix schemeN bname), alphas @ [zeta], rec_schemeT0, Syntax.NoSyn),
- (Binding.name bname, alphas, recT0, Syntax.NoSyn)];
-
- (*selectors*)
- fun mk_sel_spec (c,T) =
- Const (mk_selC rec_schemeT0 (c,T))
- :== (lambda r0 (Const (mk_selC extT (suffix ext_dest c,T))$parent_more r0));
- val sel_specs = map mk_sel_spec fields_more;
-
- (*updates*)
-
- fun mk_upd_spec (c,T) =
- let
- val new = mk_upd' updN c (Free (base c,T-->T)) extT(*(parent_more r0)*);
- in Const (mk_updC updateN rec_schemeT0 (c,T))$(Free (base c,T-->T))$r0
- :== (parent_more_upd new r0)
- end;
- val upd_specs = map mk_upd_spec fields_more;
-
- (*derived operations*)
- val make_spec = Const (full makeN, all_types ---> recT0) $$ all_vars :==
- mk_rec (all_vars @ [HOLogic.unit]) 0;
- val fields_spec = Const (full fields_selN, types ---> Type extension) $$ vars :==
- mk_rec (all_vars @ [HOLogic.unit]) parent_len;
- val extend_spec =
- Const (full extendN, recT0-->moreT-->rec_schemeT0) $ r_unit0 $ more :==
- mk_rec ((map (mk_sel r_unit0) all_fields) @ [more]) 0;
- val truncate_spec = Const (full truncateN, rec_schemeT0 --> recT0) $ r0 :==
- mk_rec ((map (mk_sel r0) all_fields) @ [HOLogic.unit]) 0;
-
- (* 2st stage: defs_thy *)
-
- fun mk_defs () =
- extension_thy
- |> Sign.add_trfuns
- ([],[],field_tr's, [])
- |> Sign.add_advanced_trfuns
- ([],[],adv_ext_tr's @ adv_record_type_tr's @ adv_record_type_abbr_tr's,[])
- |> Sign.parent_path
- |> Sign.add_tyabbrs_i recordT_specs
- |> Sign.add_path bname
- |> Sign.add_consts_i
- (map2 (fn (x, T) => fn mx => (Binding.name x, T, mx))
- sel_decls (field_syntax @ [Syntax.NoSyn]))
- |> (Sign.add_consts_i o map (fn (x, T) => (Binding.name x, T, Syntax.NoSyn)))
- (upd_decls @ [make_decl, fields_decl, extend_decl, truncate_decl])
- |> ((PureThy.add_defs false o map (Thm.no_attributes o apfst Binding.name)) sel_specs)
- ||>> ((PureThy.add_defs false o map (Thm.no_attributes o apfst Binding.name)) upd_specs)
- ||>> ((PureThy.add_defs false o map (Thm.no_attributes o apfst Binding.name))
- [make_spec, fields_spec, extend_spec, truncate_spec])
- |-> (fn defs as ((sel_defs, upd_defs), derived_defs) =>
- fold Code.add_default_eqn sel_defs
- #> fold Code.add_default_eqn upd_defs
- #> fold Code.add_default_eqn derived_defs
- #> pair defs)
- val (((sel_defs, upd_defs), derived_defs), defs_thy) =
- timeit_msg "record trfuns/tyabbrs/selectors/updates/make/fields/extend/truncate defs:"
- mk_defs;
-
-
- (* prepare propositions *)
- val _ = timing_msg "record preparing propositions";
- val P = Free (Name.variant all_variants "P", rec_schemeT0-->HOLogic.boolT);
- val C = Free (Name.variant all_variants "C", HOLogic.boolT);
- val P_unit = Free (Name.variant all_variants "P", recT0-->HOLogic.boolT);
-
- (*selectors*)
- val sel_conv_props =
- map (fn (c, x as Free (_,T)) => mk_sel r_rec0 (c,T) === x) named_vars_more;
-
- (*updates*)
- fun mk_upd_prop (i,(c,T)) =
- let val x' = Free (Name.variant all_variants (base c ^ "'"),T-->T);
- val n = parent_fields_len + i;
- val args' = nth_map n (K (x'$nth all_vars_more n)) all_vars_more
- in mk_upd updateN c x' r_rec0 === mk_rec args' 0 end;
- val upd_conv_props = ListPair.map mk_upd_prop (idxms, fields_more);
-
- (*induct*)
- val induct_scheme_prop =
- All (map dest_Free all_vars_more) (Trueprop (P $ r_rec0)) ==> Trueprop (P $ r0);
- val induct_prop =
- (All (map dest_Free all_vars) (Trueprop (P_unit $ r_rec_unit0)),
- Trueprop (P_unit $ r_unit0));
-
- (*surjective*)
- val surjective_prop =
- let val args = map (fn (c,Free (_,T)) => mk_sel r0 (c,T)) all_named_vars_more
- in r0 === mk_rec args 0 end;
-
- (*cases*)
- val cases_scheme_prop =
- (All (map dest_Free all_vars_more)
- (Trueprop (HOLogic.mk_eq (r0,r_rec0)) ==> Trueprop C))
- ==> Trueprop C;
-
- val cases_prop =
- (All (map dest_Free all_vars)
- (Trueprop (HOLogic.mk_eq (r_unit0,r_rec_unit0)) ==> Trueprop C))
- ==> Trueprop C;
-
- (*split*)
- val split_meta_prop =
- let val P = Free (Name.variant all_variants "P", rec_schemeT0-->Term.propT) in
- Logic.mk_equals
- (All [dest_Free r0] (P $ r0), All (map dest_Free all_vars_more) (P $ r_rec0))
- end;
-
- val split_object_prop =
- let fun ALL vs t = List.foldr (fn ((v,T),t) => HOLogic.mk_all (v,T,t)) t vs
- in (ALL [dest_Free r0] (P $ r0)) === (ALL (map dest_Free all_vars_more) (P $ r_rec0))
- end;
-
-
- val split_ex_prop =
- let fun EX vs t = List.foldr (fn ((v,T),t) => HOLogic.mk_exists (v,T,t)) t vs
- in (EX [dest_Free r0] (P $ r0)) === (EX (map dest_Free all_vars_more) (P $ r_rec0))
- end;
-
- (*equality*)
- val equality_prop =
- let
- val s' = Free (rN ^ "'", rec_schemeT0)
- fun mk_sel_eq (c,Free (_,T)) = mk_sel r0 (c,T) === mk_sel s' (c,T)
- val seleqs = map mk_sel_eq all_named_vars_more
- in All (map dest_Free [r0,s']) (Logic.list_implies (seleqs,r0 === s')) end;
-
- (* 3rd stage: thms_thy *)
-
- fun prove stndrd = quick_and_dirty_prove stndrd defs_thy;
- val prove_standard = quick_and_dirty_prove true defs_thy;
-
- fun prove_simp stndrd ss simps =
- let val tac = simp_all_tac ss simps
- in fn prop => prove stndrd [] prop (K tac) end;
-
- val ss = get_simpset defs_thy;
-
- fun sel_convs_prf () = map (prove_simp false ss
- (sel_defs@ext_dest_convs)) sel_conv_props;
- val sel_convs = timeit_msg "record sel_convs proof:" sel_convs_prf;
- fun sel_convs_standard_prf () = map standard sel_convs
- val sel_convs_standard =
- timeit_msg "record sel_convs_standard proof:" sel_convs_standard_prf;
-
- fun upd_convs_prf () =
- map (prove_simp true ss (upd_defs@u_convs)) upd_conv_props;
-
- val upd_convs = timeit_msg "record upd_convs proof:" upd_convs_prf;
-
- val parent_induct = if null parents then [] else [#induct (hd (rev parents))];
-
- fun induct_scheme_prf () = prove_standard [] induct_scheme_prop (fn _ =>
- (EVERY [if null parent_induct
- then all_tac else try_param_tac rN (hd parent_induct) 1,
- try_param_tac rN ext_induct 1,
- asm_simp_tac HOL_basic_ss 1]));
- val induct_scheme = timeit_msg "record induct_scheme proof:" induct_scheme_prf;
-
- fun induct_prf () =
- let val (assm, concl) = induct_prop;
- in
- prove_standard [assm] concl (fn {prems, ...} =>
- try_param_tac rN induct_scheme 1
- THEN try_param_tac "more" @{thm unit.induct} 1
- THEN resolve_tac prems 1)
- end;
- val induct = timeit_msg "record induct proof:" induct_prf;
-
- fun surjective_prf () =
- prove_standard [] surjective_prop (fn prems =>
- (EVERY [try_param_tac rN induct_scheme 1,
- simp_tac (ss addsimps sel_convs_standard) 1]))
- val surjective = timeit_msg "record surjective proof:" surjective_prf;
-
- fun cases_scheme_prf_opt () =
- let
- val (_$(Pvar$_)) = concl_of induct_scheme;
- val ind = cterm_instantiate
- [(cterm_of defs_thy Pvar, cterm_of defs_thy
- (lambda w (HOLogic.imp$HOLogic.mk_eq(r0,w)$C)))]
- induct_scheme;
- in standard (ObjectLogic.rulify (mp OF [ind, refl])) end;
-
- fun cases_scheme_prf_noopt () =
- prove_standard [] cases_scheme_prop (fn _ =>
- EVERY [asm_full_simp_tac (HOL_basic_ss addsimps [atomize_all, atomize_imp]) 1,
- try_param_tac rN induct_scheme 1,
- rtac impI 1,
- REPEAT (etac allE 1),
- etac mp 1,
- rtac refl 1])
- val cases_scheme_prf = quick_and_dirty_prf cases_scheme_prf_noopt cases_scheme_prf_opt;
- val cases_scheme = timeit_msg "record cases_scheme proof:" cases_scheme_prf;
-
- fun cases_prf () =
- prove_standard [] cases_prop (fn _ =>
- try_param_tac rN cases_scheme 1
- THEN simp_all_tac HOL_basic_ss [unit_all_eq1]);
- val cases = timeit_msg "record cases proof:" cases_prf;
-
- fun split_meta_prf () =
- prove false [] split_meta_prop (fn _ =>
- EVERY [rtac equal_intr_rule 1, Goal.norm_hhf_tac 1,
- etac meta_allE 1, atac 1,
- rtac (prop_subst OF [surjective]) 1,
- REPEAT (etac meta_allE 1), atac 1]);
- val split_meta = timeit_msg "record split_meta proof:" split_meta_prf;
- val split_meta_standard = standard split_meta;
-
- fun split_object_prf_opt () =
- let
- val cPI= cterm_of defs_thy (lambda r0 (Trueprop (P$r0)));
- val (_$Abs(_,_,P$_)) = fst (Logic.dest_equals (concl_of split_meta_standard));
- val cP = cterm_of defs_thy P;
- val split_meta' = cterm_instantiate [(cP,cPI)] split_meta_standard;
- val (l,r) = HOLogic.dest_eq (HOLogic.dest_Trueprop split_object_prop);
- val cl = cterm_of defs_thy (HOLogic.mk_Trueprop l);
- val cr = cterm_of defs_thy (HOLogic.mk_Trueprop r);
- val thl = assume cl (*All r. P r*) (* 1 *)
- |> obj_to_meta_all (*!!r. P r*)
- |> equal_elim split_meta' (*!!n m more. P (ext n m more)*)
- |> meta_to_obj_all (*All n m more. P (ext n m more)*) (* 2*)
- |> implies_intr cl (* 1 ==> 2 *)
- val thr = assume cr (*All n m more. P (ext n m more)*)
- |> obj_to_meta_all (*!!n m more. P (ext n m more)*)
- |> equal_elim (symmetric split_meta') (*!!r. P r*)
- |> meta_to_obj_all (*All r. P r*)
- |> implies_intr cr (* 2 ==> 1 *)
- in standard (thr COMP (thl COMP iffI)) end;
-
- fun split_object_prf_noopt () =
- prove_standard [] split_object_prop (fn _ =>
- EVERY [rtac iffI 1,
- REPEAT (rtac allI 1), etac allE 1, atac 1,
- rtac allI 1, rtac induct_scheme 1,REPEAT (etac allE 1),atac 1]);
-
- val split_object_prf = quick_and_dirty_prf split_object_prf_noopt split_object_prf_opt;
- val split_object = timeit_msg "record split_object proof:" split_object_prf;
-
-
- fun split_ex_prf () =
- prove_standard [] split_ex_prop (fn _ =>
- EVERY [rtac iffI 1,
- etac exE 1,
- simp_tac (HOL_basic_ss addsimps [split_meta_standard]) 1,
- ex_inst_tac 1,
- (*REPEAT (rtac exI 1),*)
- atac 1,
- REPEAT (etac exE 1),
- rtac exI 1,
- atac 1]);
- val split_ex = timeit_msg "record split_ex proof:" split_ex_prf;
-
- fun equality_tac thms =
- let val (s'::s::eqs) = rev thms;
- val ss' = ss addsimps (s'::s::sel_convs_standard);
- val eqs' = map (simplify ss') eqs;
- in simp_tac (HOL_basic_ss addsimps (s'::s::eqs')) 1 end;
-
- fun equality_prf () = prove_standard [] equality_prop (fn {context, ...} =>
- fn st => let val [s, s'] = map #1 (rev (Tactic.innermost_params 1 st)) in
- st |> (res_inst_tac context [((rN, 0), s)] cases_scheme 1
- THEN res_inst_tac context [((rN, 0), s')] cases_scheme 1
- THEN (METAHYPS equality_tac 1))
- (* simp_all_tac ss (sel_convs) would also work but is less efficient *)
- end);
- val equality = timeit_msg "record equality proof:" equality_prf;
-
- val ((([sel_convs',upd_convs',sel_defs',upd_defs',[split_meta',split_object',split_ex'],derived_defs'],
- [surjective',equality']),[induct_scheme',induct',cases_scheme',cases']), thms_thy) =
- defs_thy
- |> (PureThy.add_thmss o map (Thm.no_attributes o apfst Binding.name))
- [("select_convs", sel_convs_standard),
- ("update_convs", upd_convs),
- ("select_defs", sel_defs),
- ("update_defs", upd_defs),
- ("splits", [split_meta_standard,split_object,split_ex]),
- ("defs", derived_defs)]
- ||>> (PureThy.add_thms o map (Thm.no_attributes o apfst Binding.name))
- [("surjective", surjective),
- ("equality", equality)]
- ||>> (PureThy.add_thms o (map o apfst o apfst) Binding.name)
- [(("induct_scheme", induct_scheme), induct_type_global (suffix schemeN name)),
- (("induct", induct), induct_type_global name),
- (("cases_scheme", cases_scheme), cases_type_global (suffix schemeN name)),
- (("cases", cases), cases_type_global name)];
-
-
- val sel_upd_simps = sel_convs' @ upd_convs';
- val iffs = [ext_inject]
- val final_thy =
- thms_thy
- |> (snd oo PureThy.add_thmss)
- [((Binding.name "simps", sel_upd_simps),
- [Simplifier.simp_add, Nitpick_Const_Simp_Thms.add]),
- ((Binding.name "iffs", iffs), [iff_add])]
- |> put_record name (make_record_info args parent fields extension induct_scheme')
- |> put_sel_upd (names @ [full_moreN]) sel_upd_simps
- |> add_record_equalities extension_id equality'
- |> add_extinjects ext_inject
- |> add_extsplit extension_name ext_split
- |> add_record_splits extension_id (split_meta',split_object',split_ex',induct_scheme')
- |> add_extfields extension_name (fields @ [(full_moreN,moreT)])
- |> add_fieldext (extension_name,snd extension) (names @ [full_moreN])
- |> Sign.parent_path;
-
- in final_thy
- end;
-
-
-(* add_record *)
-
-(*we do all preparations and error checks here, deferring the real
- work to record_definition*)
-fun gen_add_record prep_typ prep_raw_parent quiet_mode (params, bname) raw_parent raw_fields thy =
- let
- val _ = Theory.requires thy "Record" "record definitions";
- val _ = if quiet_mode then () else writeln ("Defining record " ^ quote bname ^ " ...");
-
- val ctxt = ProofContext.init thy;
-
-
- (* parents *)
-
- fun prep_inst T = fst (cert_typ ctxt T []);
-
- val parent = Option.map (apfst (map prep_inst) o prep_raw_parent ctxt) raw_parent
- handle ERROR msg => cat_error msg ("The error(s) above in parent record specification");
- val parents = add_parents thy parent [];
-
- val init_env =
- (case parent of
- NONE => []
- | SOME (types, _) => List.foldr OldTerm.add_typ_tfrees [] types);
-
-
- (* fields *)
-
- fun prep_field (c, raw_T, mx) env =
- let val (T, env') = prep_typ ctxt raw_T env handle ERROR msg =>
- cat_error msg ("The error(s) above occured in record field " ^ quote c)
- in ((c, T, mx), env') end;
-
- val (bfields, envir) = fold_map prep_field raw_fields init_env;
- val envir_names = map fst envir;
-
-
- (* args *)
-
- val defaultS = Sign.defaultS thy;
- val args = map (fn x => (x, AList.lookup (op =) envir x |> the_default defaultS)) params;
-
-
- (* errors *)
-
- val name = Sign.full_bname thy bname;
- val err_dup_record =
- if is_none (get_record thy name) then []
- else ["Duplicate definition of record " ^ quote name];
-
- val err_dup_parms =
- (case duplicates (op =) params of
- [] => []
- | dups => ["Duplicate parameter(s) " ^ commas dups]);
-
- val err_extra_frees =
- (case subtract (op =) params envir_names of
- [] => []
- | extras => ["Extra free type variable(s) " ^ commas extras]);
-
- val err_no_fields = if null bfields then ["No fields present"] else [];
-
- val err_dup_fields =
- (case duplicates (op =) (map #1 bfields) of
- [] => []
- | dups => ["Duplicate field(s) " ^ commas_quote dups]);
-
- val err_bad_fields =
- if forall (not_equal moreN o #1) bfields then []
- else ["Illegal field name " ^ quote moreN];
-
- val err_dup_sorts =
- (case duplicates (op =) envir_names of
- [] => []
- | dups => ["Inconsistent sort constraints for " ^ commas dups]);
-
- val errs =
- err_dup_record @ err_dup_parms @ err_extra_frees @ err_no_fields @
- err_dup_fields @ err_bad_fields @ err_dup_sorts;
- in
- if null errs then () else error (cat_lines errs) ;
- thy |> record_definition (args, bname) parent parents bfields
- end
- handle ERROR msg => cat_error msg ("Failed to define record " ^ quote bname);
-
-val add_record = gen_add_record read_typ read_raw_parent;
-val add_record_i = gen_add_record cert_typ (K I);
-
-(* setup theory *)
-
-val setup =
- Sign.add_trfuns ([], parse_translation, [], []) #>
- Sign.add_advanced_trfuns ([], adv_parse_translation, [], []) #>
- Simplifier.map_simpset (fn ss =>
- ss addsimprocs [record_simproc, record_upd_simproc, record_eq_simproc]);
-
-(* outer syntax *)
-
-local structure P = OuterParse and K = OuterKeyword in
-
-val record_decl =
- P.type_args -- P.name --
- (P.$$$ "=" |-- Scan.option (P.typ --| P.$$$ "+") -- Scan.repeat1 P.const);
-
-val _ =
- OuterSyntax.command "record" "define extensible record" K.thy_decl
- (record_decl >> (fn (x, (y, z)) => Toplevel.theory (add_record false x y z)));
-
-end;
-
-end;
-
-
-structure BasicRecordPackage: BASIC_RECORD_PACKAGE = RecordPackage;
-open BasicRecordPackage;
--- a/src/HOL/Tools/refute.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/refute.ML Fri Jun 19 21:08:07 2009 +0200
@@ -526,7 +526,7 @@
fun is_IDT_constructor thy (s, T) =
(case body_type T of
Type (s', _) =>
- (case DatatypePackage.get_datatype_constrs thy s' of
+ (case Datatype.get_datatype_constrs thy s' of
SOME constrs =>
List.exists (fn (cname, cty) =>
cname = s andalso Sign.typ_instance thy (T, cty)) constrs
@@ -545,7 +545,7 @@
fun is_IDT_recursor thy (s, T) =
let
val rec_names = Symtab.fold (append o #rec_names o snd)
- (DatatypePackage.get_datatypes thy) []
+ (Datatype.get_datatypes thy) []
in
(* I'm not quite sure if checking the name 's' is sufficient, *)
(* or if we should also check the type 'T'. *)
@@ -834,7 +834,7 @@
(* axiomatic type classes *)
| Type ("itself", [T1]) => collect_type_axioms (axs, T1)
| Type (s, Ts) =>
- (case DatatypePackage.get_datatype thy s of
+ (case Datatype.get_datatype thy s of
SOME info => (* inductive datatype *)
(* only collect relevant type axioms for the argument types *)
Library.foldl collect_type_axioms (axs, Ts)
@@ -969,7 +969,7 @@
Type ("fun", [T1, T2]) => collect_types T1 (collect_types T2 acc)
| Type ("prop", []) => acc
| Type (s, Ts) =>
- (case DatatypePackage.get_datatype thy s of
+ (case Datatype.get_datatype thy s of
SOME info => (* inductive datatype *)
let
val index = #index info
@@ -1181,7 +1181,7 @@
(* TODO: no warning needed for /positive/ occurrences of IDTs *)
val maybe_spurious = Library.exists (fn
Type (s, _) =>
- (case DatatypePackage.get_datatype thy s of
+ (case Datatype.get_datatype thy s of
SOME info => (* inductive datatype *)
let
val index = #index info
@@ -1986,7 +1986,7 @@
val (typs, terms) = model
(* Term.typ -> (interpretation * model * arguments) option *)
fun interpret_term (Type (s, Ts)) =
- (case DatatypePackage.get_datatype thy s of
+ (case Datatype.get_datatype thy s of
SOME info => (* inductive datatype *)
let
(* int option -- only recursive IDTs have an associated depth *)
@@ -2120,7 +2120,7 @@
HOLogic_empty_set) pairss
end
| Type (s, Ts) =>
- (case DatatypePackage.get_datatype thy s of
+ (case Datatype.get_datatype thy s of
SOME info =>
(case AList.lookup (op =) typs T of
SOME 0 =>
@@ -2185,7 +2185,7 @@
Const (s, T) =>
(case body_type T of
Type (s', Ts') =>
- (case DatatypePackage.get_datatype thy s' of
+ (case Datatype.get_datatype thy s' of
SOME info => (* body type is an inductive datatype *)
let
val index = #index info
@@ -2675,7 +2675,7 @@
end
else
NONE (* not a recursion operator of this datatype *)
- ) (DatatypePackage.get_datatypes thy) NONE
+ ) (Datatype.get_datatypes thy) NONE
| _ => (* head of term is not a constant *)
NONE;
@@ -3224,7 +3224,7 @@
fun IDT_printer thy model T intr assignment =
(case T of
Type (s, Ts) =>
- (case DatatypePackage.get_datatype thy s of
+ (case Datatype.get_datatype thy s of
SOME info => (* inductive datatype *)
let
val (typs, _) = model
--- a/src/HOL/Tools/res_atp.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/res_atp.ML Fri Jun 19 21:08:07 2009 +0200
@@ -476,7 +476,7 @@
| occ _ = false
in occ end;
-fun is_recordtype T = not (null (RecordPackage.dest_recTs T));
+fun is_recordtype T = not (null (Record.dest_recTs T));
(*Unwanted equalities include
(1) those between a variable that does not properly occur in the second operand,
--- a/src/HOL/Tools/specification_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-(* Title: HOL/Tools/specification_package.ML
- Author: Sebastian Skalberg, TU Muenchen
-
-Package for defining constants by specification.
-*)
-
-signature SPECIFICATION_PACKAGE =
-sig
- val add_specification: string option -> (bstring * xstring * bool) list ->
- theory * thm -> theory * thm
-end
-
-structure SpecificationPackage: SPECIFICATION_PACKAGE =
-struct
-
-(* actual code *)
-
-local
- fun mk_definitional [] arg = arg
- | mk_definitional ((thname,cname,covld)::cos) (thy,thm) =
- case HOLogic.dest_Trueprop (concl_of thm) of
- Const("Ex",_) $ P =>
- let
- val ctype = domain_type (type_of P)
- val cname_full = Sign.intern_const thy cname
- val cdefname = if thname = ""
- then Thm.def_name (Long_Name.base_name cname)
- else thname
- val def_eq = Logic.mk_equals (Const(cname_full,ctype),
- HOLogic.choice_const ctype $ P)
- val (thms, thy') = PureThy.add_defs covld [((Binding.name cdefname, def_eq),[])] thy
- val thm' = [thm,hd thms] MRS @{thm exE_some}
- in
- mk_definitional cos (thy',thm')
- end
- | _ => raise THM ("Internal error: Bad specification theorem",0,[thm])
-
- fun mk_axiomatic axname cos arg =
- let
- fun process [] (thy,tm) =
- let
- val (thms, thy') = PureThy.add_axioms [((Binding.name axname, HOLogic.mk_Trueprop tm),[])] thy
- in
- (thy',hd thms)
- end
- | process ((thname,cname,covld)::cos) (thy,tm) =
- case tm of
- Const("Ex",_) $ P =>
- let
- val ctype = domain_type (type_of P)
- val cname_full = Sign.intern_const thy cname
- val cdefname = if thname = ""
- then Thm.def_name (Long_Name.base_name cname)
- else thname
- val co = Const(cname_full,ctype)
- val thy' = Theory.add_finals_i covld [co] thy
- val tm' = case P of
- Abs(_, _, bodt) => subst_bound (co, bodt)
- | _ => P $ co
- in
- process cos (thy',tm')
- end
- | _ => raise TERM ("Internal error: Bad specification theorem",[tm])
- in
- process cos arg
- end
-
-in
-fun proc_exprop axiomatic cos arg =
- case axiomatic of
- SOME axname => mk_axiomatic axname cos (apsnd (HOLogic.dest_Trueprop o concl_of) arg)
- | NONE => mk_definitional cos arg
-end
-
-fun add_specification axiomatic cos arg =
- arg |> apsnd Thm.freezeT
- |> proc_exprop axiomatic cos
- |> apsnd standard
-
-
-(* Collect all intances of constants in term *)
-
-fun collect_consts ( t $ u,tms) = collect_consts (u,collect_consts (t,tms))
- | collect_consts ( Abs(_,_,t),tms) = collect_consts (t,tms)
- | collect_consts (tm as Const _,tms) = insert (op aconv) tm tms
- | collect_consts ( _,tms) = tms
-
-(* Complementing Type.varify... *)
-
-fun unvarify t fmap =
- let
- val fmap' = map Library.swap fmap
- fun unthaw (f as (a, S)) =
- (case AList.lookup (op =) fmap' a of
- NONE => TVar f
- | SOME (b, _) => TFree (b, S))
- in
- map_types (map_type_tvar unthaw) t
- end
-
-(* The syntactic meddling needed to setup add_specification for work *)
-
-fun process_spec axiomatic cos alt_props thy =
- let
- fun zip3 [] [] [] = []
- | zip3 (x::xs) (y::ys) (z::zs) = (x,y,z)::zip3 xs ys zs
- | zip3 _ _ _ = error "SpecificationPackage.process_spec internal error"
-
- fun myfoldr f [x] = x
- | myfoldr f (x::xs) = f (x,myfoldr f xs)
- | myfoldr f [] = error "SpecificationPackage.process_spec internal error"
-
- val rew_imps = alt_props |>
- map (ObjectLogic.atomize o Thm.cterm_of thy o Syntax.read_prop_global thy o snd)
- val props' = rew_imps |>
- map (HOLogic.dest_Trueprop o term_of o snd o Thm.dest_equals o cprop_of)
-
- fun proc_single prop =
- let
- val frees = OldTerm.term_frees prop
- val _ = forall (fn v => Sign.of_sort thy (type_of v,HOLogic.typeS)) frees
- orelse error "Specificaton: Only free variables of sort 'type' allowed"
- val prop_closed = List.foldr (fn ((vname,T),prop) => HOLogic.mk_all (vname,T,prop)) prop (map dest_Free frees)
- in
- (prop_closed,frees)
- end
-
- val props'' = map proc_single props'
- val frees = map snd props''
- val prop = myfoldr HOLogic.mk_conj (map fst props'')
- val cprop = cterm_of thy (HOLogic.mk_Trueprop prop)
-
- val (vmap, prop_thawed) = Type.varify [] prop
- val thawed_prop_consts = collect_consts (prop_thawed,[])
- val (altcos,overloaded) = Library.split_list cos
- val (names,sconsts) = Library.split_list altcos
- val consts = map (Syntax.read_term_global thy) sconsts
- val _ = not (Library.exists (not o Term.is_Const) consts)
- orelse error "Specification: Non-constant found as parameter"
-
- fun proc_const c =
- let
- val (_, c') = Type.varify [] c
- val (cname,ctyp) = dest_Const c'
- in
- case List.filter (fn t => let val (name,typ) = dest_Const t
- in name = cname andalso Sign.typ_equiv thy (typ, ctyp)
- end) thawed_prop_consts of
- [] => error ("Specification: No suitable instances of constant \"" ^ Syntax.string_of_term_global thy c ^ "\" found")
- | [cf] => unvarify cf vmap
- | _ => error ("Specification: Several variations of \"" ^ Syntax.string_of_term_global thy c ^ "\" found (try applying explicit type constraints)")
- end
- val proc_consts = map proc_const consts
- fun mk_exist (c,prop) =
- let
- val T = type_of c
- val cname = Long_Name.base_name (fst (dest_Const c))
- val vname = if Syntax.is_identifier cname
- then cname
- else "x"
- in
- HOLogic.exists_const T $ Abs(vname,T,Term.abstract_over (c,prop))
- end
- val ex_prop = List.foldr mk_exist prop proc_consts
- val cnames = map (fst o dest_Const) proc_consts
- fun post_process (arg as (thy,thm)) =
- let
- fun inst_all thy (thm,v) =
- let
- val cv = cterm_of thy v
- val cT = ctyp_of_term cv
- val spec' = instantiate' [SOME cT] [NONE,SOME cv] spec
- in
- thm RS spec'
- end
- fun remove_alls frees thm =
- Library.foldl (inst_all (Thm.theory_of_thm thm)) (thm,frees)
- fun process_single ((name,atts),rew_imp,frees) args =
- let
- fun undo_imps thm =
- equal_elim (symmetric rew_imp) thm
-
- fun add_final (arg as (thy, thm)) =
- if name = ""
- then arg |> Library.swap
- else (writeln (" " ^ name ^ ": " ^ (Display.string_of_thm thm));
- PureThy.store_thm (Binding.name name, thm) thy)
- in
- args |> apsnd (remove_alls frees)
- |> apsnd undo_imps
- |> apsnd standard
- |> Thm.theory_attributes (map (Attrib.attribute thy) atts)
- |> add_final
- |> Library.swap
- end
-
- fun process_all [proc_arg] args =
- process_single proc_arg args
- | process_all (proc_arg::rest) (thy,thm) =
- let
- val single_th = thm RS conjunct1
- val rest_th = thm RS conjunct2
- val (thy',_) = process_single proc_arg (thy,single_th)
- in
- process_all rest (thy',rest_th)
- end
- | process_all [] _ = error "SpecificationPackage.process_spec internal error"
- val alt_names = map fst alt_props
- val _ = if exists (fn(name,_) => not (name = "")) alt_names
- then writeln "specification"
- else ()
- in
- arg |> apsnd Thm.freezeT
- |> process_all (zip3 alt_names rew_imps frees)
- end
-
- fun after_qed [[thm]] = ProofContext.theory (fn thy =>
- #1 (post_process (add_specification axiomatic (zip3 names cnames overloaded) (thy, thm))));
- in
- thy
- |> ProofContext.init
- |> Proof.theorem_i NONE after_qed [[(HOLogic.mk_Trueprop ex_prop, [])]]
- end;
-
-
-(* outer syntax *)
-
-local structure P = OuterParse and K = OuterKeyword in
-
-val opt_name = Scan.optional (P.name --| P.$$$ ":") ""
-val opt_overloaded = P.opt_keyword "overloaded";
-
-val specification_decl =
- P.$$$ "(" |-- Scan.repeat1 (opt_name -- P.term -- opt_overloaded) --| P.$$$ ")" --
- Scan.repeat1 ((SpecParse.opt_thm_name ":" >> apfst Binding.name_of) -- P.prop)
-
-val _ =
- OuterSyntax.command "specification" "define constants by specification" K.thy_goal
- (specification_decl >> (fn (cos,alt_props) =>
- Toplevel.print o (Toplevel.theory_to_proof
- (process_spec NONE cos alt_props))))
-
-val ax_specification_decl =
- P.name --
- (P.$$$ "(" |-- Scan.repeat1 (opt_name -- P.term -- opt_overloaded) --| P.$$$ ")" --
- Scan.repeat1 ((SpecParse.opt_thm_name ":" >> apfst Binding.name_of) -- P.prop))
-
-val _ =
- OuterSyntax.command "ax_specification" "define constants by specification" K.thy_goal
- (ax_specification_decl >> (fn (axname,(cos,alt_props)) =>
- Toplevel.print o (Toplevel.theory_to_proof
- (process_spec (SOME axname) cos alt_props))))
-
-end
-
-
-end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/typecopy.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,157 @@
+(* Title: HOL/Tools/typecopy.ML
+ Author: Florian Haftmann, TU Muenchen
+
+Introducing copies of types using trivial typedefs; datatype-like abstraction.
+*)
+
+signature TYPECOPY =
+sig
+ type info = {
+ vs: (string * sort) list,
+ constr: string,
+ typ: typ,
+ inject: thm,
+ proj: string * typ,
+ proj_def: thm
+ }
+ val typecopy: binding * string list -> typ -> (binding * binding) option
+ -> theory -> (string * info) * theory
+ val get_typecopies: theory -> string list
+ val get_info: theory -> string -> info option
+ val interpretation: (string -> theory -> theory) -> theory -> theory
+ val add_default_code: string -> theory -> theory
+ val print_typecopies: theory -> unit
+ val setup: theory -> theory
+end;
+
+structure Typecopy: TYPECOPY =
+struct
+
+(* theory data *)
+
+type info = {
+ vs: (string * sort) list,
+ constr: string,
+ typ: typ,
+ inject: thm,
+ proj: string * typ,
+ proj_def: thm
+};
+
+structure TypecopyData = TheoryDataFun
+(
+ type T = info Symtab.table;
+ val empty = Symtab.empty;
+ val copy = I;
+ val extend = I;
+ fun merge _ = Symtab.merge (K true);
+);
+
+fun print_typecopies thy =
+ let
+ val tab = TypecopyData.get thy;
+ fun mk (tyco, { vs, constr, typ, proj = (proj, _), ... } : info) =
+ (Pretty.block o Pretty.breaks) [
+ Syntax.pretty_typ_global thy (Type (tyco, map TFree vs)),
+ Pretty.str "=",
+ (Pretty.str o Sign.extern_const thy) constr,
+ Syntax.pretty_typ_global thy typ,
+ Pretty.block [Pretty.str "(", (Pretty.str o Sign.extern_const thy) proj, Pretty.str ")"]];
+ in
+ (Pretty.writeln o Pretty.block o Pretty.fbreaks)
+ (Pretty.str "type copies:" :: map mk (Symtab.dest tab))
+ end;
+
+val get_typecopies = Symtab.keys o TypecopyData.get;
+val get_info = Symtab.lookup o TypecopyData.get;
+
+
+(* interpretation of type copies *)
+
+structure TypecopyInterpretation = InterpretationFun(type T = string val eq = op =);
+val interpretation = TypecopyInterpretation.interpretation;
+
+
+(* declaring typecopies *)
+
+fun typecopy (raw_tyco, raw_vs) raw_ty constr_proj thy =
+ let
+ val ty = Sign.certify_typ thy raw_ty;
+ val vs =
+ AList.make (the_default HOLogic.typeS o AList.lookup (op =) (Term.add_tfreesT ty [])) raw_vs;
+ val tac = Tactic.rtac UNIV_witness 1;
+ fun add_info tyco ( { abs_type = ty_abs, rep_type = ty_rep, Abs_name = c_abs,
+ Rep_name = c_rep, Abs_inject = inject,
+ Abs_inverse = inverse, ... } : Typedef.info ) thy =
+ let
+ val exists_thm =
+ UNIV_I
+ |> Drule.instantiate' [SOME (ctyp_of thy (Logic.varifyT ty_rep))] [];
+ val inject' = inject OF [exists_thm, exists_thm];
+ val proj_def = inverse OF [exists_thm];
+ val info = {
+ vs = vs,
+ constr = c_abs,
+ typ = ty_rep,
+ inject = inject',
+ proj = (c_rep, ty_abs --> ty_rep),
+ proj_def = proj_def
+ };
+ in
+ thy
+ |> (TypecopyData.map o Symtab.update_new) (tyco, info)
+ |> TypecopyInterpretation.data tyco
+ |> pair (tyco, info)
+ end
+ in
+ thy
+ |> Typedef.add_typedef false (SOME raw_tyco) (raw_tyco, map fst vs, NoSyn)
+ (HOLogic.mk_UNIV ty) (Option.map swap constr_proj) tac
+ |-> (fn (tyco, info) => add_info tyco info)
+ end;
+
+
+(* default code setup *)
+
+fun add_default_code tyco thy =
+ let
+ val SOME { constr = constr_name, proj = (proj, _), proj_def = proj_eq, vs = raw_vs,
+ typ = ty_rep, ... } = get_info thy tyco;
+ val SOME { Rep_inject = proj_inject, ... } = Typedef.get_info thy tyco;
+ val constr = (constr_name, Logic.unvarifyT (Sign.the_const_type thy constr_name));
+ val vs = (map dest_TFree o snd o dest_Type) (Type (tyco, map TFree raw_vs));
+ val ty = Type (tyco, map TFree vs);
+ val proj = Const (proj, ty --> ty_rep);
+ val (t_x, t_y) = (Free ("x", ty), Free ("y", ty));
+ val eq_lhs = Const (@{const_name eq_class.eq}, ty --> ty --> HOLogic.boolT)
+ $ t_x $ t_y;
+ val eq_rhs = HOLogic.mk_eq (proj $ t_x, proj $ t_y);
+ val eq = (HOLogic.mk_Trueprop o HOLogic.mk_eq) (eq_lhs, eq_rhs);
+ fun tac eq_thm = Class.intro_classes_tac []
+ THEN (Simplifier.rewrite_goals_tac
+ (map Simpdata.mk_eq [eq_thm, @{thm eq}, proj_inject]))
+ THEN ALLGOALS (rtac @{thm refl});
+ fun mk_eq_refl thy = @{thm HOL.eq_refl}
+ |> Thm.instantiate
+ ([pairself (Thm.ctyp_of thy) (TVar (("'a", 0), @{sort eq}), Logic.varifyT ty)], [])
+ |> AxClass.unoverload thy;
+ in
+ thy
+ |> Code.add_datatype [constr]
+ |> Code.add_eqn proj_eq
+ |> TheoryTarget.instantiation ([tyco], vs, [HOLogic.class_eq])
+ |> `(fn lthy => Syntax.check_term lthy eq)
+ |-> (fn eq => Specification.definition
+ (NONE, (Attrib.empty_binding, eq)))
+ |-> (fn (_, (_, eq_thm)) =>
+ Class.prove_instantiation_exit_result Morphism.thm
+ (fn _ => fn eq_thm => tac eq_thm) eq_thm)
+ |-> (fn eq_thm => Code.add_eqn eq_thm)
+ |> (fn thy => Code.add_nbe_eqn (mk_eq_refl thy) thy)
+ end;
+
+val setup =
+ TypecopyInterpretation.init
+ #> interpretation add_default_code
+
+end;
--- a/src/HOL/Tools/typecopy_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-(* Title: HOL/Tools/typecopy_package.ML
- Author: Florian Haftmann, TU Muenchen
-
-Introducing copies of types using trivial typedefs; datatype-like abstraction.
-*)
-
-signature TYPECOPY_PACKAGE =
-sig
- type info = {
- vs: (string * sort) list,
- constr: string,
- typ: typ,
- inject: thm,
- proj: string * typ,
- proj_def: thm
- }
- val typecopy: binding * string list -> typ -> (binding * binding) option
- -> theory -> (string * info) * theory
- val get_typecopies: theory -> string list
- val get_info: theory -> string -> info option
- val interpretation: (string -> theory -> theory) -> theory -> theory
- val add_default_code: string -> theory -> theory
- val print_typecopies: theory -> unit
- val setup: theory -> theory
-end;
-
-structure TypecopyPackage: TYPECOPY_PACKAGE =
-struct
-
-(* theory data *)
-
-type info = {
- vs: (string * sort) list,
- constr: string,
- typ: typ,
- inject: thm,
- proj: string * typ,
- proj_def: thm
-};
-
-structure TypecopyData = TheoryDataFun
-(
- type T = info Symtab.table;
- val empty = Symtab.empty;
- val copy = I;
- val extend = I;
- fun merge _ = Symtab.merge (K true);
-);
-
-fun print_typecopies thy =
- let
- val tab = TypecopyData.get thy;
- fun mk (tyco, { vs, constr, typ, proj = (proj, _), ... } : info) =
- (Pretty.block o Pretty.breaks) [
- Syntax.pretty_typ_global thy (Type (tyco, map TFree vs)),
- Pretty.str "=",
- (Pretty.str o Sign.extern_const thy) constr,
- Syntax.pretty_typ_global thy typ,
- Pretty.block [Pretty.str "(", (Pretty.str o Sign.extern_const thy) proj, Pretty.str ")"]];
- in
- (Pretty.writeln o Pretty.block o Pretty.fbreaks)
- (Pretty.str "type copies:" :: map mk (Symtab.dest tab))
- end;
-
-val get_typecopies = Symtab.keys o TypecopyData.get;
-val get_info = Symtab.lookup o TypecopyData.get;
-
-
-(* interpretation of type copies *)
-
-structure TypecopyInterpretation = InterpretationFun(type T = string val eq = op =);
-val interpretation = TypecopyInterpretation.interpretation;
-
-
-(* declaring typecopies *)
-
-fun typecopy (raw_tyco, raw_vs) raw_ty constr_proj thy =
- let
- val ty = Sign.certify_typ thy raw_ty;
- val vs =
- AList.make (the_default HOLogic.typeS o AList.lookup (op =) (Term.add_tfreesT ty [])) raw_vs;
- val tac = Tactic.rtac UNIV_witness 1;
- fun add_info tyco ( { abs_type = ty_abs, rep_type = ty_rep, Abs_name = c_abs,
- Rep_name = c_rep, Abs_inject = inject,
- Abs_inverse = inverse, ... } : TypedefPackage.info ) thy =
- let
- val exists_thm =
- UNIV_I
- |> Drule.instantiate' [SOME (ctyp_of thy (Logic.varifyT ty_rep))] [];
- val inject' = inject OF [exists_thm, exists_thm];
- val proj_def = inverse OF [exists_thm];
- val info = {
- vs = vs,
- constr = c_abs,
- typ = ty_rep,
- inject = inject',
- proj = (c_rep, ty_abs --> ty_rep),
- proj_def = proj_def
- };
- in
- thy
- |> (TypecopyData.map o Symtab.update_new) (tyco, info)
- |> TypecopyInterpretation.data tyco
- |> pair (tyco, info)
- end
- in
- thy
- |> TypedefPackage.add_typedef false (SOME raw_tyco) (raw_tyco, map fst vs, NoSyn)
- (HOLogic.mk_UNIV ty) (Option.map swap constr_proj) tac
- |-> (fn (tyco, info) => add_info tyco info)
- end;
-
-
-(* default code setup *)
-
-fun add_default_code tyco thy =
- let
- val SOME { constr = constr_name, proj = (proj, _), proj_def = proj_eq, vs = raw_vs,
- typ = ty_rep, ... } = get_info thy tyco;
- val SOME { Rep_inject = proj_inject, ... } = TypedefPackage.get_info thy tyco;
- val constr = (constr_name, Logic.unvarifyT (Sign.the_const_type thy constr_name));
- val vs = (map dest_TFree o snd o dest_Type) (Type (tyco, map TFree raw_vs));
- val ty = Type (tyco, map TFree vs);
- val proj = Const (proj, ty --> ty_rep);
- val (t_x, t_y) = (Free ("x", ty), Free ("y", ty));
- val eq_lhs = Const (@{const_name eq_class.eq}, ty --> ty --> HOLogic.boolT)
- $ t_x $ t_y;
- val eq_rhs = HOLogic.mk_eq (proj $ t_x, proj $ t_y);
- val eq = (HOLogic.mk_Trueprop o HOLogic.mk_eq) (eq_lhs, eq_rhs);
- fun tac eq_thm = Class.intro_classes_tac []
- THEN (Simplifier.rewrite_goals_tac
- (map Simpdata.mk_eq [eq_thm, @{thm eq}, proj_inject]))
- THEN ALLGOALS (rtac @{thm refl});
- fun mk_eq_refl thy = @{thm HOL.eq_refl}
- |> Thm.instantiate
- ([pairself (Thm.ctyp_of thy) (TVar (("'a", 0), @{sort eq}), Logic.varifyT ty)], [])
- |> AxClass.unoverload thy;
- in
- thy
- |> Code.add_datatype [constr]
- |> Code.add_eqn proj_eq
- |> TheoryTarget.instantiation ([tyco], vs, [HOLogic.class_eq])
- |> `(fn lthy => Syntax.check_term lthy eq)
- |-> (fn eq => Specification.definition
- (NONE, (Attrib.empty_binding, eq)))
- |-> (fn (_, (_, eq_thm)) =>
- Class.prove_instantiation_exit_result Morphism.thm
- (fn _ => fn eq_thm => tac eq_thm) eq_thm)
- |-> (fn eq_thm => Code.add_eqn eq_thm)
- |> (fn thy => Code.add_nbe_eqn (mk_eq_refl thy) thy)
- end;
-
-val setup =
- TypecopyInterpretation.init
- #> interpretation add_default_code
-
-end;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/typedef.ML Fri Jun 19 21:08:07 2009 +0200
@@ -0,0 +1,270 @@
+(* Title: HOL/Tools/typedef.ML
+ Author: Markus Wenzel and Stefan Berghofer, TU Muenchen
+
+Gordon/HOL-style type definitions: create a new syntactic type
+represented by a non-empty subset.
+*)
+
+signature TYPEDEF =
+sig
+ type info =
+ {rep_type: typ, abs_type: typ, Rep_name: string, Abs_name: string, inhabited: thm,
+ type_definition: thm, set_def: thm option, Rep: thm, Rep_inverse: thm,
+ Abs_inverse: thm, Rep_inject: thm, Abs_inject: thm, Rep_cases: thm, Abs_cases: thm,
+ Rep_induct: thm, Abs_induct: thm}
+ val get_info: theory -> string -> info option
+ val add_typedef: bool -> binding option -> binding * string list * mixfix ->
+ term -> (binding * binding) option -> tactic -> theory -> (string * info) * theory
+ val typedef: (bool * binding) * (binding * string list * mixfix) * term
+ * (binding * binding) option -> theory -> Proof.state
+ val typedef_cmd: (bool * binding) * (binding * string list * mixfix) * string
+ * (binding * binding) option -> theory -> Proof.state
+ val interpretation: (string -> theory -> theory) -> theory -> theory
+ val setup: theory -> theory
+end;
+
+structure Typedef: TYPEDEF =
+struct
+
+(** type definitions **)
+
+(* theory data *)
+
+type info =
+ {rep_type: typ, abs_type: typ, Rep_name: string, Abs_name: string, inhabited: thm,
+ type_definition: thm, set_def: thm option, Rep: thm, Rep_inverse: thm,
+ Abs_inverse: thm, Rep_inject: thm, Abs_inject: thm, Rep_cases: thm, Abs_cases: thm,
+ Rep_induct: thm, Abs_induct: thm};
+
+structure TypedefData = TheoryDataFun
+(
+ type T = info Symtab.table;
+ val empty = Symtab.empty;
+ val copy = I;
+ val extend = I;
+ fun merge _ tabs : T = Symtab.merge (K true) tabs;
+);
+
+val get_info = Symtab.lookup o TypedefData.get;
+fun put_info name info = TypedefData.map (Symtab.update (name, info));
+
+
+(* prepare_typedef *)
+
+fun declare_type_name a = Variable.declare_constraints (Logic.mk_type (TFree (a, dummyS)));
+
+structure TypedefInterpretation = InterpretationFun(type T = string val eq = op =);
+val interpretation = TypedefInterpretation.interpretation;
+
+fun prepare_typedef prep_term def name (t, vs, mx) raw_set opt_morphs thy =
+ let
+ val _ = Theory.requires thy "Typedef" "typedefs";
+ val ctxt = ProofContext.init thy;
+
+ val full = Sign.full_name thy;
+ val full_name = full name;
+ val bname = Binding.name_of name;
+
+ (*rhs*)
+ val set = prep_term (ctxt |> fold declare_type_name vs) raw_set;
+ val setT = Term.fastype_of set;
+ val rhs_tfrees = Term.add_tfrees set [];
+ val rhs_tfreesT = Term.add_tfreesT setT [];
+ val oldT = HOLogic.dest_setT setT handle TYPE _ =>
+ error ("Not a set type: " ^ quote (Syntax.string_of_typ ctxt setT));
+
+ (*lhs*)
+ val defS = Sign.defaultS thy;
+ val lhs_tfrees = map (fn v => (v, the_default defS (AList.lookup (op =) rhs_tfrees v))) vs;
+ val args_setT = lhs_tfrees
+ |> filter (member (op =) rhs_tfrees andf (not o member (op =) rhs_tfreesT))
+ |> map TFree;
+
+ val tname = Binding.map_name (Syntax.type_name mx) t;
+ val full_tname = full tname;
+ val newT = Type (full_tname, map TFree lhs_tfrees);
+
+ val (Rep_name, Abs_name) =
+ (case opt_morphs of
+ NONE => (Binding.prefix_name "Rep_" name, Binding.prefix_name "Abs_" name)
+ | SOME morphs => morphs);
+ val setT' = map Term.itselfT args_setT ---> setT;
+ val setC = Term.list_comb (Const (full_name, setT'), map Logic.mk_type args_setT);
+ val RepC = Const (full Rep_name, newT --> oldT);
+ val AbsC = Const (full Abs_name, oldT --> newT);
+
+ (*inhabitance*)
+ fun mk_inhabited A =
+ HOLogic.mk_Trueprop (HOLogic.mk_exists ("x", oldT, HOLogic.mk_mem (Free ("x", oldT), A)));
+ val set' = if def then setC else set;
+ val goal' = mk_inhabited set';
+ val goal = mk_inhabited set;
+ val goal_pat = mk_inhabited (Var (the_default (bname, 0) (Syntax.read_variable bname), setT));
+
+ (*axiomatization*)
+ val typedef_name = Binding.prefix_name "type_definition_" name;
+ val typedefC =
+ Const (@{const_name type_definition},
+ (newT --> oldT) --> (oldT --> newT) --> setT --> HOLogic.boolT);
+ val typedef_prop = Logic.mk_implies (goal', HOLogic.mk_Trueprop (typedefC $ RepC $ AbsC $ set'));
+ val typedef_deps = Term.add_consts set' [];
+
+ (*set definition*)
+ fun add_def theory =
+ if def then
+ theory
+ |> Sign.add_consts_i [(name, setT', NoSyn)]
+ |> PureThy.add_defs false [Thm.no_attributes (apfst (Binding.name)
+ (PrimitiveDefs.mk_defpair (setC, set)))]
+ |-> (fn [th] => pair (SOME th))
+ else (NONE, theory);
+ fun contract_def NONE th = th
+ | contract_def (SOME def_eq) th =
+ let
+ val cert = Thm.cterm_of (Thm.theory_of_thm def_eq);
+ val goal_eq = MetaSimplifier.rewrite true [def_eq] (cert goal');
+ in Drule.standard (Drule.equal_elim_rule2 OF [goal_eq, th]) end;
+
+ fun typedef_result inhabited =
+ ObjectLogic.typedecl (t, vs, mx)
+ #> snd
+ #> Sign.add_consts_i
+ [(Rep_name, newT --> oldT, NoSyn),
+ (Abs_name, oldT --> newT, NoSyn)]
+ #> add_def
+ #-> (fn set_def =>
+ PureThy.add_axioms [((typedef_name, typedef_prop),
+ [Thm.rule_attribute (K (fn cond_axm => contract_def set_def inhabited RS cond_axm))])]
+ ##>> pair set_def)
+ ##> Theory.add_deps "" (dest_Const RepC) typedef_deps
+ ##> Theory.add_deps "" (dest_Const AbsC) typedef_deps
+ #-> (fn ([type_definition], set_def) => fn thy1 =>
+ let
+ fun make th = Drule.standard (th OF [type_definition]);
+ val ([Rep, Rep_inverse, Abs_inverse, Rep_inject, Abs_inject,
+ Rep_cases, Abs_cases, Rep_induct, Abs_induct], thy2) =
+ thy1
+ |> Sign.add_path (Binding.name_of name)
+ |> PureThy.add_thms
+ [((Rep_name, make @{thm type_definition.Rep}), []),
+ ((Binding.suffix_name "_inverse" Rep_name, make @{thm type_definition.Rep_inverse}), []),
+ ((Binding.suffix_name "_inverse" Abs_name, make @{thm type_definition.Abs_inverse}), []),
+ ((Binding.suffix_name "_inject" Rep_name, make @{thm type_definition.Rep_inject}), []),
+ ((Binding.suffix_name "_inject" Abs_name, make @{thm type_definition.Abs_inject}), []),
+ ((Binding.suffix_name "_cases" Rep_name, make @{thm type_definition.Rep_cases}),
+ [RuleCases.case_names [Binding.name_of Rep_name], Induct.cases_pred full_name]),
+ ((Binding.suffix_name "_cases" Abs_name, make @{thm type_definition.Abs_cases}),
+ [RuleCases.case_names [Binding.name_of Abs_name], Induct.cases_type full_tname]),
+ ((Binding.suffix_name "_induct" Rep_name, make @{thm type_definition.Rep_induct}),
+ [RuleCases.case_names [Binding.name_of Rep_name], Induct.induct_pred full_name]),
+ ((Binding.suffix_name "_induct" Abs_name, make @{thm type_definition.Abs_induct}),
+ [RuleCases.case_names [Binding.name_of Abs_name], Induct.induct_type full_tname])]
+ ||> Sign.parent_path;
+ val info = {rep_type = oldT, abs_type = newT,
+ Rep_name = full Rep_name, Abs_name = full Abs_name,
+ inhabited = inhabited, type_definition = type_definition, set_def = set_def,
+ Rep = Rep, Rep_inverse = Rep_inverse, Abs_inverse = Abs_inverse,
+ Rep_inject = Rep_inject, Abs_inject = Abs_inject, Rep_cases = Rep_cases,
+ Abs_cases = Abs_cases, Rep_induct = Rep_induct, Abs_induct = Abs_induct};
+ in
+ thy2
+ |> put_info full_tname info
+ |> TypedefInterpretation.data full_tname
+ |> pair (full_tname, info)
+ end);
+
+
+ (* errors *)
+
+ fun show_names pairs = commas_quote (map fst pairs);
+
+ val illegal_vars =
+ if null (Term.add_vars set []) andalso null (Term.add_tvars set []) then []
+ else ["Illegal schematic variable(s) on rhs"];
+
+ val dup_lhs_tfrees =
+ (case duplicates (op =) lhs_tfrees of [] => []
+ | dups => ["Duplicate type variables on lhs: " ^ show_names dups]);
+
+ val extra_rhs_tfrees =
+ (case fold (remove (op =)) lhs_tfrees rhs_tfrees of [] => []
+ | extras => ["Extra type variables on rhs: " ^ show_names extras]);
+
+ val illegal_frees =
+ (case Term.add_frees set [] of [] => []
+ | xs => ["Illegal variables on rhs: " ^ show_names xs]);
+
+ val errs = illegal_vars @ dup_lhs_tfrees @ extra_rhs_tfrees @ illegal_frees;
+ val _ = if null errs then () else error (cat_lines errs);
+
+ (*test theory errors now!*)
+ val test_thy = Theory.copy thy;
+ val _ = test_thy
+ |> typedef_result (setmp quick_and_dirty true (SkipProof.make_thm test_thy) goal);
+
+ in (set, goal, goal_pat, typedef_result) end
+ handle ERROR msg =>
+ cat_error msg ("The error(s) above occurred in typedef " ^ quote (Binding.str_of name));
+
+
+(* add_typedef: tactic interface *)
+
+fun add_typedef def opt_name typ set opt_morphs tac thy =
+ let
+ val name = the_default (#1 typ) opt_name;
+ val (set, goal, _, typedef_result) =
+ prepare_typedef Syntax.check_term def name typ set opt_morphs thy;
+ val inhabited = Goal.prove_global thy [] [] goal (K tac)
+ handle ERROR msg => cat_error msg
+ ("Failed to prove non-emptiness of " ^ quote (Syntax.string_of_term_global thy set));
+ in typedef_result inhabited thy end;
+
+
+(* typedef: proof interface *)
+
+local
+
+fun gen_typedef prep_term ((def, name), typ, set, opt_morphs) thy =
+ let
+ val (_, goal, goal_pat, typedef_result) =
+ prepare_typedef prep_term def name typ set opt_morphs thy;
+ fun after_qed [[th]] = ProofContext.theory (snd o typedef_result th);
+ in Proof.theorem_i NONE after_qed [[(goal, [goal_pat])]] (ProofContext.init thy) end;
+
+in
+
+val typedef = gen_typedef Syntax.check_term;
+val typedef_cmd = gen_typedef Syntax.read_term;
+
+end;
+
+
+
+(** outer syntax **)
+
+local structure P = OuterParse in
+
+val _ = OuterKeyword.keyword "morphisms";
+
+val typedef_decl =
+ Scan.optional (P.$$$ "(" |--
+ ((P.$$$ "open" >> K false) -- Scan.option P.binding || P.binding >> (fn s => (true, SOME s)))
+ --| P.$$$ ")") (true, NONE) --
+ (P.type_args -- P.binding) -- P.opt_infix -- (P.$$$ "=" |-- P.term) --
+ Scan.option (P.$$$ "morphisms" |-- P.!!! (P.binding -- P.binding));
+
+fun mk_typedef ((((((def, opt_name), (vs, t)), mx), A), morphs)) =
+ typedef_cmd ((def, the_default (Binding.map_name (Syntax.type_name mx) t) opt_name),
+ (t, vs, mx), A, morphs);
+
+val _ =
+ OuterSyntax.command "typedef" "HOL type definition (requires non-emptiness proof)"
+ OuterKeyword.thy_goal
+ (typedef_decl >> (Toplevel.print oo (Toplevel.theory_to_proof o mk_typedef)));
+
+end;
+
+
+val setup = TypedefInterpretation.init;
+
+end;
--- a/src/HOL/Tools/typedef_codegen.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Tools/typedef_codegen.ML Fri Jun 19 21:08:07 2009 +0200
@@ -24,7 +24,7 @@
val id = Codegen.mk_qual_id module (Codegen.get_const_id gr'' s)
in SOME (Codegen.mk_app brack (Codegen.str id) ps, gr'') end;
fun lookup f T =
- (case TypedefPackage.get_info thy (get_name T) of
+ (case Typedef.get_info thy (get_name T) of
NONE => ""
| SOME info => f info);
in
@@ -45,7 +45,7 @@
| mk_tyexpr ps s = Pretty.list "(" (") " ^ s) ps;
fun typedef_tycodegen thy defs dep module brack (Type (s, Ts)) gr =
- (case TypedefPackage.get_info thy s of
+ (case Typedef.get_info thy s of
NONE => NONE
| SOME {abs_type as newT as Type (tname, Us), rep_type = oldT, Abs_name, Rep_name, ...} =>
if is_some (Codegen.get_assoc_type thy tname) then NONE else
--- a/src/HOL/Tools/typedef_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,270 +0,0 @@
-(* Title: HOL/Tools/typedef_package.ML
- Author: Markus Wenzel and Stefan Berghofer, TU Muenchen
-
-Gordon/HOL-style type definitions: create a new syntactic type
-represented by a non-empty subset.
-*)
-
-signature TYPEDEF_PACKAGE =
-sig
- type info =
- {rep_type: typ, abs_type: typ, Rep_name: string, Abs_name: string, inhabited: thm,
- type_definition: thm, set_def: thm option, Rep: thm, Rep_inverse: thm,
- Abs_inverse: thm, Rep_inject: thm, Abs_inject: thm, Rep_cases: thm, Abs_cases: thm,
- Rep_induct: thm, Abs_induct: thm}
- val get_info: theory -> string -> info option
- val add_typedef: bool -> binding option -> binding * string list * mixfix ->
- term -> (binding * binding) option -> tactic -> theory -> (string * info) * theory
- val typedef: (bool * binding) * (binding * string list * mixfix) * term
- * (binding * binding) option -> theory -> Proof.state
- val typedef_cmd: (bool * binding) * (binding * string list * mixfix) * string
- * (binding * binding) option -> theory -> Proof.state
- val interpretation: (string -> theory -> theory) -> theory -> theory
- val setup: theory -> theory
-end;
-
-structure TypedefPackage: TYPEDEF_PACKAGE =
-struct
-
-(** type definitions **)
-
-(* theory data *)
-
-type info =
- {rep_type: typ, abs_type: typ, Rep_name: string, Abs_name: string, inhabited: thm,
- type_definition: thm, set_def: thm option, Rep: thm, Rep_inverse: thm,
- Abs_inverse: thm, Rep_inject: thm, Abs_inject: thm, Rep_cases: thm, Abs_cases: thm,
- Rep_induct: thm, Abs_induct: thm};
-
-structure TypedefData = TheoryDataFun
-(
- type T = info Symtab.table;
- val empty = Symtab.empty;
- val copy = I;
- val extend = I;
- fun merge _ tabs : T = Symtab.merge (K true) tabs;
-);
-
-val get_info = Symtab.lookup o TypedefData.get;
-fun put_info name info = TypedefData.map (Symtab.update (name, info));
-
-
-(* prepare_typedef *)
-
-fun declare_type_name a = Variable.declare_constraints (Logic.mk_type (TFree (a, dummyS)));
-
-structure TypedefInterpretation = InterpretationFun(type T = string val eq = op =);
-val interpretation = TypedefInterpretation.interpretation;
-
-fun prepare_typedef prep_term def name (t, vs, mx) raw_set opt_morphs thy =
- let
- val _ = Theory.requires thy "Typedef" "typedefs";
- val ctxt = ProofContext.init thy;
-
- val full = Sign.full_name thy;
- val full_name = full name;
- val bname = Binding.name_of name;
-
- (*rhs*)
- val set = prep_term (ctxt |> fold declare_type_name vs) raw_set;
- val setT = Term.fastype_of set;
- val rhs_tfrees = Term.add_tfrees set [];
- val rhs_tfreesT = Term.add_tfreesT setT [];
- val oldT = HOLogic.dest_setT setT handle TYPE _ =>
- error ("Not a set type: " ^ quote (Syntax.string_of_typ ctxt setT));
-
- (*lhs*)
- val defS = Sign.defaultS thy;
- val lhs_tfrees = map (fn v => (v, the_default defS (AList.lookup (op =) rhs_tfrees v))) vs;
- val args_setT = lhs_tfrees
- |> filter (member (op =) rhs_tfrees andf (not o member (op =) rhs_tfreesT))
- |> map TFree;
-
- val tname = Binding.map_name (Syntax.type_name mx) t;
- val full_tname = full tname;
- val newT = Type (full_tname, map TFree lhs_tfrees);
-
- val (Rep_name, Abs_name) =
- (case opt_morphs of
- NONE => (Binding.prefix_name "Rep_" name, Binding.prefix_name "Abs_" name)
- | SOME morphs => morphs);
- val setT' = map Term.itselfT args_setT ---> setT;
- val setC = Term.list_comb (Const (full_name, setT'), map Logic.mk_type args_setT);
- val RepC = Const (full Rep_name, newT --> oldT);
- val AbsC = Const (full Abs_name, oldT --> newT);
-
- (*inhabitance*)
- fun mk_inhabited A =
- HOLogic.mk_Trueprop (HOLogic.mk_exists ("x", oldT, HOLogic.mk_mem (Free ("x", oldT), A)));
- val set' = if def then setC else set;
- val goal' = mk_inhabited set';
- val goal = mk_inhabited set;
- val goal_pat = mk_inhabited (Var (the_default (bname, 0) (Syntax.read_variable bname), setT));
-
- (*axiomatization*)
- val typedef_name = Binding.prefix_name "type_definition_" name;
- val typedefC =
- Const (@{const_name type_definition},
- (newT --> oldT) --> (oldT --> newT) --> setT --> HOLogic.boolT);
- val typedef_prop = Logic.mk_implies (goal', HOLogic.mk_Trueprop (typedefC $ RepC $ AbsC $ set'));
- val typedef_deps = Term.add_consts set' [];
-
- (*set definition*)
- fun add_def theory =
- if def then
- theory
- |> Sign.add_consts_i [(name, setT', NoSyn)]
- |> PureThy.add_defs false [Thm.no_attributes (apfst (Binding.name)
- (PrimitiveDefs.mk_defpair (setC, set)))]
- |-> (fn [th] => pair (SOME th))
- else (NONE, theory);
- fun contract_def NONE th = th
- | contract_def (SOME def_eq) th =
- let
- val cert = Thm.cterm_of (Thm.theory_of_thm def_eq);
- val goal_eq = MetaSimplifier.rewrite true [def_eq] (cert goal');
- in Drule.standard (Drule.equal_elim_rule2 OF [goal_eq, th]) end;
-
- fun typedef_result inhabited =
- ObjectLogic.typedecl (t, vs, mx)
- #> snd
- #> Sign.add_consts_i
- [(Rep_name, newT --> oldT, NoSyn),
- (Abs_name, oldT --> newT, NoSyn)]
- #> add_def
- #-> (fn set_def =>
- PureThy.add_axioms [((typedef_name, typedef_prop),
- [Thm.rule_attribute (K (fn cond_axm => contract_def set_def inhabited RS cond_axm))])]
- ##>> pair set_def)
- ##> Theory.add_deps "" (dest_Const RepC) typedef_deps
- ##> Theory.add_deps "" (dest_Const AbsC) typedef_deps
- #-> (fn ([type_definition], set_def) => fn thy1 =>
- let
- fun make th = Drule.standard (th OF [type_definition]);
- val ([Rep, Rep_inverse, Abs_inverse, Rep_inject, Abs_inject,
- Rep_cases, Abs_cases, Rep_induct, Abs_induct], thy2) =
- thy1
- |> Sign.add_path (Binding.name_of name)
- |> PureThy.add_thms
- [((Rep_name, make @{thm type_definition.Rep}), []),
- ((Binding.suffix_name "_inverse" Rep_name, make @{thm type_definition.Rep_inverse}), []),
- ((Binding.suffix_name "_inverse" Abs_name, make @{thm type_definition.Abs_inverse}), []),
- ((Binding.suffix_name "_inject" Rep_name, make @{thm type_definition.Rep_inject}), []),
- ((Binding.suffix_name "_inject" Abs_name, make @{thm type_definition.Abs_inject}), []),
- ((Binding.suffix_name "_cases" Rep_name, make @{thm type_definition.Rep_cases}),
- [RuleCases.case_names [Binding.name_of Rep_name], Induct.cases_pred full_name]),
- ((Binding.suffix_name "_cases" Abs_name, make @{thm type_definition.Abs_cases}),
- [RuleCases.case_names [Binding.name_of Abs_name], Induct.cases_type full_tname]),
- ((Binding.suffix_name "_induct" Rep_name, make @{thm type_definition.Rep_induct}),
- [RuleCases.case_names [Binding.name_of Rep_name], Induct.induct_pred full_name]),
- ((Binding.suffix_name "_induct" Abs_name, make @{thm type_definition.Abs_induct}),
- [RuleCases.case_names [Binding.name_of Abs_name], Induct.induct_type full_tname])]
- ||> Sign.parent_path;
- val info = {rep_type = oldT, abs_type = newT,
- Rep_name = full Rep_name, Abs_name = full Abs_name,
- inhabited = inhabited, type_definition = type_definition, set_def = set_def,
- Rep = Rep, Rep_inverse = Rep_inverse, Abs_inverse = Abs_inverse,
- Rep_inject = Rep_inject, Abs_inject = Abs_inject, Rep_cases = Rep_cases,
- Abs_cases = Abs_cases, Rep_induct = Rep_induct, Abs_induct = Abs_induct};
- in
- thy2
- |> put_info full_tname info
- |> TypedefInterpretation.data full_tname
- |> pair (full_tname, info)
- end);
-
-
- (* errors *)
-
- fun show_names pairs = commas_quote (map fst pairs);
-
- val illegal_vars =
- if null (Term.add_vars set []) andalso null (Term.add_tvars set []) then []
- else ["Illegal schematic variable(s) on rhs"];
-
- val dup_lhs_tfrees =
- (case duplicates (op =) lhs_tfrees of [] => []
- | dups => ["Duplicate type variables on lhs: " ^ show_names dups]);
-
- val extra_rhs_tfrees =
- (case fold (remove (op =)) lhs_tfrees rhs_tfrees of [] => []
- | extras => ["Extra type variables on rhs: " ^ show_names extras]);
-
- val illegal_frees =
- (case Term.add_frees set [] of [] => []
- | xs => ["Illegal variables on rhs: " ^ show_names xs]);
-
- val errs = illegal_vars @ dup_lhs_tfrees @ extra_rhs_tfrees @ illegal_frees;
- val _ = if null errs then () else error (cat_lines errs);
-
- (*test theory errors now!*)
- val test_thy = Theory.copy thy;
- val _ = test_thy
- |> typedef_result (setmp quick_and_dirty true (SkipProof.make_thm test_thy) goal);
-
- in (set, goal, goal_pat, typedef_result) end
- handle ERROR msg =>
- cat_error msg ("The error(s) above occurred in typedef " ^ quote (Binding.str_of name));
-
-
-(* add_typedef: tactic interface *)
-
-fun add_typedef def opt_name typ set opt_morphs tac thy =
- let
- val name = the_default (#1 typ) opt_name;
- val (set, goal, _, typedef_result) =
- prepare_typedef Syntax.check_term def name typ set opt_morphs thy;
- val inhabited = Goal.prove_global thy [] [] goal (K tac)
- handle ERROR msg => cat_error msg
- ("Failed to prove non-emptiness of " ^ quote (Syntax.string_of_term_global thy set));
- in typedef_result inhabited thy end;
-
-
-(* typedef: proof interface *)
-
-local
-
-fun gen_typedef prep_term ((def, name), typ, set, opt_morphs) thy =
- let
- val (_, goal, goal_pat, typedef_result) =
- prepare_typedef prep_term def name typ set opt_morphs thy;
- fun after_qed [[th]] = ProofContext.theory (snd o typedef_result th);
- in Proof.theorem_i NONE after_qed [[(goal, [goal_pat])]] (ProofContext.init thy) end;
-
-in
-
-val typedef = gen_typedef Syntax.check_term;
-val typedef_cmd = gen_typedef Syntax.read_term;
-
-end;
-
-
-
-(** outer syntax **)
-
-local structure P = OuterParse in
-
-val _ = OuterKeyword.keyword "morphisms";
-
-val typedef_decl =
- Scan.optional (P.$$$ "(" |--
- ((P.$$$ "open" >> K false) -- Scan.option P.binding || P.binding >> (fn s => (true, SOME s)))
- --| P.$$$ ")") (true, NONE) --
- (P.type_args -- P.binding) -- P.opt_infix -- (P.$$$ "=" |-- P.term) --
- Scan.option (P.$$$ "morphisms" |-- P.!!! (P.binding -- P.binding));
-
-fun mk_typedef ((((((def, opt_name), (vs, t)), mx), A), morphs)) =
- typedef_cmd ((def, the_default (Binding.map_name (Syntax.type_name mx) t) opt_name),
- (t, vs, mx), A, morphs);
-
-val _ =
- OuterSyntax.command "typedef" "HOL type definition (requires non-emptiness proof)"
- OuterKeyword.thy_goal
- (typedef_decl >> (Toplevel.print oo (Toplevel.theory_to_proof o mk_typedef)));
-
-end;
-
-
-val setup = TypedefInterpretation.init;
-
-end;
--- a/src/HOL/Typedef.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Typedef.thy Fri Jun 19 21:08:07 2009 +0200
@@ -7,8 +7,8 @@
theory Typedef
imports Set
uses
- ("Tools/typedef_package.ML")
- ("Tools/typecopy_package.ML")
+ ("Tools/typedef.ML")
+ ("Tools/typecopy.ML")
("Tools/typedef_codegen.ML")
begin
@@ -115,8 +115,8 @@
end
-use "Tools/typedef_package.ML" setup TypedefPackage.setup
-use "Tools/typecopy_package.ML" setup TypecopyPackage.setup
+use "Tools/typedef.ML" setup Typedef.setup
+use "Tools/typecopy.ML" setup Typecopy.setup
use "Tools/typedef_codegen.ML" setup TypedefCodegen.setup
end
--- a/src/HOL/Typerep.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/Typerep.thy Fri Jun 19 21:08:07 2009 +0200
@@ -64,7 +64,7 @@
in
add_typerep @{type_name fun}
-#> TypedefPackage.interpretation ensure_typerep
+#> Typedef.interpretation ensure_typerep
#> Code.type_interpretation (ensure_typerep o fst)
end
--- a/src/HOL/ex/Records.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/ex/Records.thy Fri Jun 19 21:08:07 2009 +0200
@@ -247,8 +247,8 @@
text {* In some cases its convenient to automatically split
(quantified) records. For this purpose there is the simproc @{ML [source]
-"RecordPackage.record_split_simproc"} and the tactic @{ML [source]
-"RecordPackage.record_split_simp_tac"}. The simplification procedure
+"Record.record_split_simproc"} and the tactic @{ML [source]
+"Record.record_split_simp_tac"}. The simplification procedure
only splits the records, whereas the tactic also simplifies the
resulting goal with the standard record simplification rules. A
(generalized) predicate on the record is passed as parameter that
@@ -257,51 +257,51 @@
the quantifier). The value @{ML "0"} indicates no split, a value
greater @{ML "0"} splits up to the given bound of record extension and
finally the value @{ML "~1"} completely splits the record.
-@{ML [source] "RecordPackage.record_split_simp_tac"} additionally takes a list of
+@{ML [source] "Record.record_split_simp_tac"} additionally takes a list of
equations for simplification and can also split fixed record variables.
*}
lemma "(\<forall>r. P (xpos r)) \<longrightarrow> (\<forall>x. P x)"
apply (tactic {* simp_tac
- (HOL_basic_ss addsimprocs [RecordPackage.record_split_simproc (K ~1)]) 1*})
+ (HOL_basic_ss addsimprocs [Record.record_split_simproc (K ~1)]) 1*})
apply simp
done
lemma "(\<forall>r. P (xpos r)) \<longrightarrow> (\<forall>x. P x)"
- apply (tactic {* RecordPackage.record_split_simp_tac [] (K ~1) 1*})
+ apply (tactic {* Record.record_split_simp_tac [] (K ~1) 1*})
apply simp
done
lemma "(\<exists>r. P (xpos r)) \<longrightarrow> (\<exists>x. P x)"
apply (tactic {* simp_tac
- (HOL_basic_ss addsimprocs [RecordPackage.record_split_simproc (K ~1)]) 1*})
+ (HOL_basic_ss addsimprocs [Record.record_split_simproc (K ~1)]) 1*})
apply simp
done
lemma "(\<exists>r. P (xpos r)) \<longrightarrow> (\<exists>x. P x)"
- apply (tactic {* RecordPackage.record_split_simp_tac [] (K ~1) 1*})
+ apply (tactic {* Record.record_split_simp_tac [] (K ~1) 1*})
apply simp
done
lemma "\<And>r. P (xpos r) \<Longrightarrow> (\<exists>x. P x)"
apply (tactic {* simp_tac
- (HOL_basic_ss addsimprocs [RecordPackage.record_split_simproc (K ~1)]) 1*})
+ (HOL_basic_ss addsimprocs [Record.record_split_simproc (K ~1)]) 1*})
apply auto
done
lemma "\<And>r. P (xpos r) \<Longrightarrow> (\<exists>x. P x)"
- apply (tactic {* RecordPackage.record_split_simp_tac [] (K ~1) 1*})
+ apply (tactic {* Record.record_split_simp_tac [] (K ~1) 1*})
apply auto
done
lemma "P (xpos r) \<Longrightarrow> (\<exists>x. P x)"
- apply (tactic {* RecordPackage.record_split_simp_tac [] (K ~1) 1*})
+ apply (tactic {* Record.record_split_simp_tac [] (K ~1) 1*})
apply auto
done
lemma fixes r shows "P (xpos r) \<Longrightarrow> (\<exists>x. P x)"
- apply (tactic {* RecordPackage.record_split_simp_tac [] (K ~1) 1*})
+ apply (tactic {* Record.record_split_simp_tac [] (K ~1) 1*})
apply auto
done
@@ -314,7 +314,7 @@
have "\<exists>x. P x"
using pre
apply -
- apply (tactic {* RecordPackage.record_split_simp_tac [] (K ~1) 1*})
+ apply (tactic {* Record.record_split_simp_tac [] (K ~1) 1*})
apply auto
done
}
@@ -322,13 +322,13 @@
qed
text {* The effect of simproc @{ML [source]
-"RecordPackage.record_ex_sel_eq_simproc"} is illustrated by the
+"Record.record_ex_sel_eq_simproc"} is illustrated by the
following lemma.
*}
lemma "\<exists>r. xpos r = x"
apply (tactic {*simp_tac
- (HOL_basic_ss addsimprocs [RecordPackage.record_ex_sel_eq_simproc]) 1*})
+ (HOL_basic_ss addsimprocs [Record.record_ex_sel_eq_simproc]) 1*})
done
--- a/src/HOL/ex/predicate_compile.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOL/ex/predicate_compile.ML Fri Jun 19 21:08:07 2009 +0200
@@ -50,7 +50,7 @@
(* reference to preprocessing of InductiveSet package *)
-val ind_set_codegen_preproc = InductiveSetPackage.codegen_preproc;
+val ind_set_codegen_preproc = Inductive_Set.codegen_preproc;
(** fundamentals **)
@@ -279,7 +279,7 @@
end;
fun fetch_pred_data thy name =
- case try (InductivePackage.the_inductive (ProofContext.init thy)) name of
+ case try (Inductive.the_inductive (ProofContext.init thy)) name of
SOME (info as (_, result)) =>
let
fun is_intro_of intro =
@@ -288,7 +288,7 @@
in (fst (dest_Const const) = name) end;
val intros = map (preprocess_intro thy) (filter is_intro_of (#intrs result))
val elim = nth (#elims result) (find_index (fn s => s = name) (#names (fst info)))
- val nparams = length (InductivePackage.params_of (#raw_induct result))
+ val nparams = length (Inductive.params_of (#raw_induct result))
in (intros, elim, nparams) end
| NONE => error ("No such predicate: " ^ quote name)
@@ -333,7 +333,7 @@
let
val cnstrs = flat (maps
(map (fn (_, (Tname, _, cs)) => map (apsnd (rpair Tname o length)) cs) o #descr o snd)
- (Symtab.dest (DatatypePackage.get_datatypes thy)));
+ (Symtab.dest (Datatype.get_datatypes thy)));
fun check t = (case strip_comb t of
(Free _, []) => true
| (Const (s, T), ts) => (case (AList.lookup (op =) cnstrs s, body_type T) of
@@ -568,7 +568,7 @@
val v = Free (name, T);
val v' = Free (name', T);
in
- lambda v (fst (DatatypePackage.make_case
+ lambda v (fst (Datatype.make_case
(ProofContext.init thy) false [] v
[(mk_tuple out_ts,
if null eqs'' then success_t
@@ -875,7 +875,7 @@
(* else false *)
fun is_constructor thy t =
if (is_Type (fastype_of t)) then
- (case DatatypePackage.get_datatype thy ((fst o dest_Type o fastype_of) t) of
+ (case Datatype.get_datatype thy ((fst o dest_Type o fastype_of) t) of
NONE => false
| SOME info => (let
val constr_consts = maps (fn (_, (_, _, constrs)) => map fst constrs) (#descr info)
@@ -954,7 +954,7 @@
fun prove_match thy (out_ts : term list) = let
fun get_case_rewrite t =
if (is_constructor thy t) then let
- val case_rewrites = (#case_rewrites (DatatypePackage.the_datatype thy
+ val case_rewrites = (#case_rewrites (Datatype.the_datatype thy
((fst o dest_Type o fastype_of) t)))
in case_rewrites @ (flat (map get_case_rewrite (snd (strip_comb t)))) end
else []
@@ -1067,7 +1067,7 @@
| select_sup n i = (rtac @{thm supI2})::(select_sup (n - 1) (i - 1));
fun prove_one_direction thy all_vs param_vs modes clauses ((pred, T), mode) = let
-(* val ind_result = InductivePackage.the_inductive (ProofContext.init thy) pred
+(* val ind_result = Inductive.the_inductive (ProofContext.init thy) pred
val index = find_index (fn s => s = pred) (#names (fst ind_result))
val (_, T) = dest_Const (nth (#preds (snd ind_result)) index) *)
val nargs = length (binder_types T) - nparams_of thy pred
@@ -1093,7 +1093,7 @@
fun split_term_tac (Free _) = all_tac
| split_term_tac t =
if (is_constructor thy t) then let
- val info = DatatypePackage.the_datatype thy ((fst o dest_Type o fastype_of) t)
+ val info = Datatype.the_datatype thy ((fst o dest_Type o fastype_of) t)
val num_of_constrs = length (#case_rewrites info)
(* special treatment of pairs -- because of fishing *)
val split_rules = case (fst o dest_Type o fastype_of) t of
@@ -1414,7 +1414,7 @@
fun dependencies_of thy name =
let
fun is_inductive_predicate thy name =
- is_some (try (InductivePackage.the_inductive (ProofContext.init thy)) name)
+ is_some (try (Inductive.the_inductive (ProofContext.init thy)) name)
val (intro, elim, nparams) = fetch_pred_data thy name
val data = mk_pred_data ((intro, SOME elim, nparams), [])
val intros = map Thm.prop_of (#intros (rep_pred_data data))
--- a/src/HOLCF/IOA/Modelcheck/MuIOA.thy Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOLCF/IOA/Modelcheck/MuIOA.thy Fri Jun 19 21:08:07 2009 +0200
@@ -184,7 +184,7 @@
val subgoal = Thm.term_of csubgoal;
in
(let
- val weak_case_congs = (map (#weak_case_cong o snd) o Symtab.dest o DatatypePackage.get_datatypes) sign;
+ val weak_case_congs = (map (#weak_case_cong o snd) o Symtab.dest o Datatype.get_datatypes) sign;
val concl = Logic.strip_imp_concl subgoal;
val ic_str = delete_ul_string(Syntax.string_of_term_global sign (IntC sign concl));
val ia_str = delete_ul_string(Syntax.string_of_term_global sign (IntA sign concl));
--- a/src/HOLCF/Tools/pcpodef_package.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/HOLCF/Tools/pcpodef_package.ML Fri Jun 19 21:08:07 2009 +0200
@@ -73,7 +73,7 @@
fun make_po tac thy1 =
let
val ((_, {type_definition, set_def, ...}), thy2) = thy1
- |> TypedefPackage.add_typedef def (SOME name) (t, vs, mx) set opt_morphs tac;
+ |> Typedef.add_typedef def (SOME name) (t, vs, mx) set opt_morphs tac;
val lthy3 = thy2
|> TheoryTarget.instantiation ([full_tname], lhs_tfrees, @{sort po});
val below_def' = Syntax.check_term lthy3 below_def;
--- a/src/Tools/code/code_haskell.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/Tools/code/code_haskell.ML Fri Jun 19 21:08:07 2009 +0200
@@ -70,7 +70,7 @@
])
| pr_term tyvars thm vars fxy (IVar v) =
(str o Code_Printer.lookup_var vars) v
- | pr_term tyvars thm vars fxy (t as _ `|-> _) =
+ | pr_term tyvars thm vars fxy (t as _ `|=> _) =
let
val (binds, t') = Code_Thingol.unfold_abs t;
fun pr ((v, pat), ty) = pr_bind tyvars thm BR ((SOME v, pat), ty);
@@ -240,7 +240,7 @@
end
| pr_stmt (_, Code_Thingol.Classinst ((class, (tyco, vs)), (_, classparam_insts))) =
let
- val split_abs_pure = (fn (v, _) `|-> t => SOME (v, t) | _ => NONE);
+ val split_abs_pure = (fn (v, _) `|=> t => SOME (v, t) | _ => NONE);
val unfold_abs_pure = Code_Thingol.unfoldr split_abs_pure;
val tyvars = Code_Printer.intro_vars (map fst vs) init_syms;
fun pr_instdef ((classparam, c_inst), (thm, _)) = case syntax_const classparam
--- a/src/Tools/code/code_ml.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/Tools/code/code_ml.ML Fri Jun 19 21:08:07 2009 +0200
@@ -92,7 +92,7 @@
of SOME c_ts => pr_app is_closure thm vars fxy c_ts
| NONE => brackify fxy
[pr_term is_closure thm vars NOBR t1, pr_term is_closure thm vars BR t2])
- | pr_term is_closure thm vars fxy (t as _ `|-> _) =
+ | pr_term is_closure thm vars fxy (t as _ `|=> _) =
let
val (binds, t') = Code_Thingol.unfold_abs t;
fun pr ((v, pat), ty) =
@@ -401,7 +401,7 @@
of SOME c_ts => pr_app is_closure thm vars fxy c_ts
| NONE =>
brackify fxy [pr_term is_closure thm vars NOBR t1, pr_term is_closure thm vars BR t2])
- | pr_term is_closure thm vars fxy (t as _ `|-> _) =
+ | pr_term is_closure thm vars fxy (t as _ `|=> _) =
let
val (binds, t') = Code_Thingol.unfold_abs t;
fun pr ((v, pat), ty) = pr_bind is_closure thm BR ((SOME v, pat), ty);
--- a/src/Tools/code/code_thingol.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/Tools/code/code_thingol.ML Fri Jun 19 21:08:07 2009 +0200
@@ -8,8 +8,8 @@
infix 8 `%%;
infix 4 `$;
infix 4 `$$;
-infixr 3 `|->;
-infixr 3 `|-->;
+infixr 3 `|=>;
+infixr 3 `|==>;
signature BASIC_CODE_THINGOL =
sig
@@ -25,11 +25,11 @@
IConst of const
| IVar of vname
| `$ of iterm * iterm
- | `|-> of (vname * itype) * iterm
+ | `|=> of (vname * itype) * iterm
| ICase of ((iterm * itype) * (iterm * iterm) list) * iterm;
(*((term, type), [(selector pattern, body term )]), primitive term)*)
val `$$ : iterm * iterm list -> iterm;
- val `|--> : (vname * itype) list * iterm -> iterm;
+ val `|==> : (vname * itype) list * iterm -> iterm;
type typscheme = (vname * sort) list * itype;
end;
@@ -128,21 +128,21 @@
IConst of const
| IVar of vname
| `$ of iterm * iterm
- | `|-> of (vname * itype) * iterm
+ | `|=> of (vname * itype) * iterm
| ICase of ((iterm * itype) * (iterm * iterm) list) * iterm;
(*see also signature*)
val op `$$ = Library.foldl (op `$);
-val op `|--> = Library.foldr (op `|->);
+val op `|==> = Library.foldr (op `|=>);
val unfold_app = unfoldl
(fn op `$ t => SOME t
| _ => NONE);
val split_abs =
- (fn (v, ty) `|-> (t as ICase (((IVar w, _), [(p, t')]), _)) =>
+ (fn (v, ty) `|=> (t as ICase (((IVar w, _), [(p, t')]), _)) =>
if v = w then SOME (((v, SOME p), ty), t') else SOME (((v, NONE), ty), t)
- | (v, ty) `|-> t => SOME (((v, NONE), ty), t)
+ | (v, ty) `|=> t => SOME (((v, NONE), ty), t)
| _ => NONE);
val unfold_abs = unfoldr split_abs;
@@ -161,7 +161,7 @@
fun fold_aiterms f (t as IConst _) = f t
| fold_aiterms f (t as IVar _) = f t
| fold_aiterms f (t1 `$ t2) = fold_aiterms f t1 #> fold_aiterms f t2
- | fold_aiterms f (t as _ `|-> t') = f t #> fold_aiterms f t'
+ | fold_aiterms f (t as _ `|=> t') = f t #> fold_aiterms f t'
| fold_aiterms f (ICase (_, t)) = fold_aiterms f t;
fun fold_constnames f =
@@ -173,7 +173,7 @@
fun fold_varnames f =
let
fun add (IVar v) = f v
- | add ((v, _) `|-> _) = f v
+ | add ((v, _) `|=> _) = f v
| add _ = I;
in fold_aiterms add end;
@@ -182,7 +182,7 @@
fun add _ (IConst _) = I
| add vs (IVar v) = if not (member (op =) vs v) then f v else I
| add vs (t1 `$ t2) = add vs t1 #> add vs t2
- | add vs ((v, _) `|-> t) = add (insert (op =) v vs) t
+ | add vs ((v, _) `|=> t) = add (insert (op =) v vs) t
| add vs (ICase (_, t)) = add vs t;
in add [] end;
@@ -204,7 +204,7 @@
val l = k - j;
val ctxt = (fold o fold_varnames) Name.declare ts Name.context;
val vs_tys = Name.names ctxt "a" ((curry Library.take l o curry Library.drop j) tys);
- in vs_tys `|--> IConst c `$$ ts @ map (fn (v, _) => IVar v) vs_tys end;
+ in vs_tys `|==> IConst c `$$ ts @ map (fn (v, _) => IVar v) vs_tys end;
fun contains_dictvar t =
let
@@ -218,7 +218,7 @@
fun locally_monomorphic (IConst _) = false
| locally_monomorphic (IVar _) = true
| locally_monomorphic (t `$ _) = locally_monomorphic t
- | locally_monomorphic (_ `|-> t) = locally_monomorphic t
+ | locally_monomorphic (_ `|=> t) = locally_monomorphic t
| locally_monomorphic (ICase ((_, ds), _)) = exists (locally_monomorphic o snd) ds;
@@ -397,8 +397,8 @@
| map_terms_bottom_up f (t as IVar _) = f t
| map_terms_bottom_up f (t1 `$ t2) = f
(map_terms_bottom_up f t1 `$ map_terms_bottom_up f t2)
- | map_terms_bottom_up f ((v, ty) `|-> t) = f
- ((v, ty) `|-> map_terms_bottom_up f t)
+ | map_terms_bottom_up f ((v, ty) `|=> t) = f
+ ((v, ty) `|=> map_terms_bottom_up f t)
| map_terms_bottom_up f (ICase (((t, ty), ps), t0)) = f
(ICase (((map_terms_bottom_up f t, ty), (map o pairself)
(map_terms_bottom_up f) ps), map_terms_bottom_up f t0));
@@ -581,7 +581,7 @@
in
translate_typ thy algbr funcgr ty
##>> translate_term thy algbr funcgr thm t
- #>> (fn (ty, t) => (v, ty) `|-> t)
+ #>> (fn (ty, t) => (v, ty) `|=> t)
end
| translate_term thy algbr funcgr thm (t as _ $ _) =
case strip_comb t
@@ -636,12 +636,12 @@
else map (uncurry mk_clause)
(AList.make (Code.no_args thy) case_pats ~~ ts_clause);
fun retermify ty (_, (IVar x, body)) =
- (x, ty) `|-> body
+ (x, ty) `|=> body
| retermify _ (_, (pat, body)) =
let
val (IConst (_, (_, tys)), ts) = unfold_app pat;
val vs = map2 (fn IVar x => fn ty => (x, ty)) ts tys;
- in vs `|--> body end;
+ in vs `|==> body end;
fun mk_icase const t ty clauses =
let
val (ts1, ts2) = chop t_pos (map (retermify ty) clauses);
@@ -668,7 +668,7 @@
in
fold_map (translate_typ thy algbr funcgr) tys
##>> translate_case thy algbr funcgr thm case_scheme ((c, ty), ts @ map Free vs)
- #>> (fn (tys, t) => map2 (fn (v, _) => pair v) vs tys `|--> t)
+ #>> (fn (tys, t) => map2 (fn (v, _) => pair v) vs tys `|==> t)
end
else if length ts > num_args then
translate_case thy algbr funcgr thm case_scheme ((c, ty), Library.take (num_args, ts))
--- a/src/Tools/nbe.ML Fri Jun 19 20:22:46 2009 +0200
+++ b/src/Tools/nbe.ML Fri Jun 19 21:08:07 2009 +0200
@@ -192,7 +192,7 @@
in of_iapp match_cont t' (fold_rev (cons o of_iterm NONE) ts []) end
and of_iapp match_cont (IConst (c, ((_, dss), _))) ts = constapp c dss ts
| of_iapp match_cont (IVar v) ts = nbe_apps (nbe_bound v) ts
- | of_iapp match_cont ((v, _) `|-> t) ts =
+ | of_iapp match_cont ((v, _) `|=> t) ts =
nbe_apps (nbe_abss 1 (ml_abs (ml_list [nbe_bound v]) (of_iterm NONE t))) ts
| of_iapp match_cont (ICase (((t, _), cs), t0)) ts =
nbe_apps (ml_cases (of_iterm NONE t)