3 begin |
3 begin |
4 |
4 |
5 section {* The Gory Details\label{sec:code} *} |
5 section {* The Gory Details\label{sec:code} *} |
6 |
6 |
7 text {* |
7 text {* |
8 As mentioned before the code falls roughly into three parts: code that deals |
8 As mentioned before the code falls roughly into three parts: the code that deals |
9 with the definitions, withe the induction principles and the introduction |
9 with the definitions, with the induction principles and with the introduction |
10 rules, respectively. In addition there are some administrative functions |
10 rules. In addition there are some administrative functions that string everything |
11 that string everything together. |
11 together. |
12 *} |
12 *} |
13 |
13 |
14 subsection {* Definitions *} |
14 subsection {* Definitions *} |
15 |
15 |
16 text {* |
16 text {* |
17 We first have to produce for each predicate the definition, whose general form is |
17 We first have to produce for each predicate the user specifies an appropriate |
|
18 definition, whose general form is |
18 |
19 |
19 @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"} |
20 @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"} |
20 |
21 |
21 and then ``register'' the definition inside a local theory. |
22 and then ``register'' the definition inside a local theory. |
22 To do the latter, we use the following wrapper for |
23 To do the latter, we use the following wrapper for the function |
23 @{ML LocalTheory.define}. The wrapper takes a predicate name, a syntax |
24 @{ML LocalTheory.define}. The wrapper takes a predicate name, a syntax |
24 annotation and a term representing the right-hand side of the definition. |
25 annotation and a term representing the right-hand side of the definition. |
25 *} |
26 *} |
26 |
27 |
27 ML %linenosgray{*fun make_defn ((predname, syn), trm) lthy = |
28 ML %linenosgray{*fun make_defn ((predname, mx), trm) lthy = |
28 let |
29 let |
29 val arg = ((predname, syn), (Attrib.empty_binding, trm)) |
30 val arg = ((predname, mx), (Attrib.empty_binding, trm)) |
30 val ((_, (_ , thm)), lthy') = LocalTheory.define Thm.internalK arg lthy |
31 val ((_, (_ , thm)), lthy') = LocalTheory.define Thm.internalK arg lthy |
31 in |
32 in |
32 (thm, lthy') |
33 (thm, lthy') |
33 end*} |
34 end*} |
34 |
35 |
35 text {* |
36 text {* |
36 It returns the definition (as a theorem) and the local theory in which this definition has |
37 It returns the definition (as a theorem) and the local theory in which the |
37 been made. In Line 4, @{ML internalK in Thm} is a flag attached to the |
38 definition has been made. In Line 4, @{ML internalK in Thm} is a flag |
38 theorem (others possibile flags are @{ML definitionK in Thm} and @{ML axiomK in Thm}). |
39 attached to the theorem (others possibile flags are @{ML definitionK in Thm} |
39 These flags just classify theorems and have no significant meaning, except |
40 and @{ML axiomK in Thm}). These flags just classify theorems and have no |
40 for tools that, for example, find theorems in the theorem database. We also |
41 significant meaning, except for tools that, for example, find theorems in |
41 use @{ML empty_binding in Attrib} in Line 3, since for our inductive predicates |
42 the theorem database.\footnote{FIXME: put in the section about theorems.} We |
42 the definitions do not need to have any theorem attributes. A testcase for this |
43 also use @{ML empty_binding in Attrib} in Line 3, since the definitions for |
43 function is |
44 our inductive predicates are not meant to be seen by the user and therefore |
|
45 do not need to have any theorem attributes. A testcase for this function is |
44 *} |
46 *} |
45 |
47 |
46 local_setup %gray {* fn lthy => |
48 local_setup %gray {* fn lthy => |
47 let |
49 let |
48 val arg = ((@{binding "MyTrue"}, NoSyn), @{term True}) |
50 val arg = ((@{binding "My_True"}, NoSyn), @{term True}) |
49 val (def, lthy') = make_defn arg lthy |
51 val (def, lthy') = make_defn arg lthy |
50 in |
52 in |
51 warning (str_of_thm_no_vars lthy' def); lthy' |
53 warning (str_of_thm_no_vars lthy' def); lthy' |
52 end *} |
54 end *} |
53 |
55 |
54 text {* |
56 text {* |
55 which introduces the definition @{prop "MyTrue \<equiv> True"} and then prints it out. |
57 which introduces the definition @{thm My_True_def} and then prints it out. |
56 Since we are testing the function inside \isacommand{local\_setup}, i.e., make |
58 Since we are testing the function inside \isacommand{local\_setup}, i.e., make |
57 actual changes to the ambient theory, we can query the definition with the usual |
59 actual changes to the ambient theory, we can query the definition with the usual |
58 command \isacommand{thm}: |
60 command \isacommand{thm}: |
59 |
61 |
60 \begin{isabelle} |
62 \begin{isabelle} |
61 \isacommand{thm}~@{text "MyTrue_def"}\\ |
63 \isacommand{thm}~@{thm [source] "My_True_def"}\\ |
62 @{text "> MyTrue \<equiv> True"} |
64 @{text ">"}~@{thm "My_True_def"} |
63 \end{isabelle} |
65 \end{isabelle} |
64 |
66 |
65 The next two functions construct the right-hand sides of the definitions, |
67 The next two functions construct the right-hand sides of the definitions, |
66 which are terms of the form |
68 which are terms whose general form is: |
67 |
69 |
68 @{text [display] "\<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"} |
70 @{text [display] "\<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"} |
69 |
71 |
70 When constructing them, the variables @{text "zs"} need to be chosen so that |
72 When constructing these terms, the variables @{text "zs"} need to be chosen so |
71 they do not occur in the @{text orules} and also be distinct from the @{text |
73 that they do not occur in the @{text orules} and also be distinct from the |
72 "preds"}. |
74 @{text "preds"}. |
73 |
75 |
74 |
76 |
75 The first function, named @{text defn_aux}, constructs the term for one |
77 The first function, named @{text defn_aux}, constructs the term for one |
76 particular predicate (the argument @{text "pred"} in the code below). The |
78 particular predicate (the argument @{text "pred"} in the code below). The |
77 number of arguments of this predicate is determined by the number of |
79 number of arguments of this predicate is determined by the number of |
143 (\<forall>a s t. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow> |
145 (\<forall>a s t. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow> |
144 (\<forall>a t. fresh a (Lam a t)) \<longrightarrow> |
146 (\<forall>a t. fresh a (Lam a t)) \<longrightarrow> |
145 (\<forall>a b t. \<not> a = b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh z za"} |
147 (\<forall>a b t. \<not> a = b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh z za"} |
146 |
148 |
147 |
149 |
148 The second function, named @{text defns}, has to just iterate the function |
150 The second function, named @{text defns}, has to iterate the function |
149 @{ML defn_aux} over all predicates. The argument @{text "preds"} is again |
151 @{ML defn_aux} over all predicates. The argument @{text "preds"} is again |
150 the the list of predicates as @{ML_type term}s; the argument @{text |
152 the list of predicates as @{ML_type term}s; the argument @{text |
151 "prednames"} is the list of binding names of the predicates; @{text syns} |
153 "prednames"} is the list of binding names of the predicates; @{text mxs} |
152 are the list of syntax annotations for the predicates; @{text "arg_tyss"} is |
154 are the list of syntax, or mixfix, annotations for the predicates; |
153 the list of argument-type-lists. |
155 @{text "arg_tyss"} is the list of argument-type-lists. |
154 *} |
156 *} |
155 |
157 |
156 ML %linenosgray{*fun defns rules preds prednames syns arg_typss lthy = |
158 ML %linenosgray{*fun defns rules preds prednames mxs arg_typss lthy = |
157 let |
159 let |
158 val thy = ProofContext.theory_of lthy |
160 val thy = ProofContext.theory_of lthy |
159 val orules = map (ObjectLogic.atomize_term thy) rules |
161 val orules = map (ObjectLogic.atomize_term thy) rules |
160 val defs = map (defn_aux lthy orules preds) (preds ~~ arg_typss) |
162 val defs = map (defn_aux lthy orules preds) (preds ~~ arg_typss) |
161 in |
163 in |
162 fold_map make_defn (prednames ~~ syns ~~ defs) lthy |
164 fold_map make_defn (prednames ~~ mxs ~~ defs) lthy |
163 end*} |
165 end*} |
164 |
166 |
165 text {* |
167 text {* |
166 The user will state the introduction rules using meta-implications and |
168 The user will state the introduction rules using meta-implications and |
167 meta-quanti\-fications. In Line 4, we transform these introduction rules into |
169 meta-quanti\-fications. In Line 4, we transform these introduction rules |
168 the object logic (since definitions cannot be stated with |
170 into the object logic (since definitions cannot be stated with |
169 meta-connectives). To do this transformation we have to obtain the theory |
171 meta-connectives). To do this transformation we have to obtain the theory |
170 behind the local theory (Line 3); with this theory we can use the function |
172 behind the local theory (Line 3); with this theory we can use the function |
171 @{ML ObjectLogic.atomize_term} to make the transformation (Line 4). The call |
173 @{ML ObjectLogic.atomize_term} to make the transformation (Line 4). The call |
172 to @{ML defn_aux} in Line 5 produces all right-hand sides of the |
174 to @{ML defn_aux} in Line 5 produces all right-hand sides of the |
173 definitions. The actual definitions are then made in Line 7. The result |
175 definitions. The actual definitions are then made in Line 7. The result of |
174 of the function is a list of theorems and a local theory. A testcase for |
176 the function is a list of theorems and a local theory (the theorems are |
175 this function is |
177 registered with the local theory). A testcase for this function is |
176 *} |
178 *} |
177 |
179 |
178 local_setup %gray {* fn lthy => |
180 local_setup %gray {* fn lthy => |
179 let |
181 let |
180 val (defs, lthy') = |
182 val (defs, lthy') = |
181 defns eo_rules eo_preds eo_prednames eo_syns eo_arg_tyss lthy |
183 defns eo_rules eo_preds eo_prednames eo_mxs eo_arg_tyss lthy |
182 in |
184 in |
183 warning (str_of_thms_no_vars lthy' defs); lthy |
185 warning (str_of_thms_no_vars lthy' defs); lthy |
184 end *} |
186 end *} |
185 |
187 |
186 text {* |
188 text {* |
966 and the introduction rules @{text "rule_spec"}. |
968 and the introduction rules @{text "rule_spec"}. |
967 *} |
969 *} |
968 |
970 |
969 ML %linenosgray{*fun add_inductive pred_specs rule_specs lthy = |
971 ML %linenosgray{*fun add_inductive pred_specs rule_specs lthy = |
970 let |
972 let |
971 val syns = map snd pred_specs |
973 val mxs = map snd pred_specs |
972 val pred_specs' = map fst pred_specs |
974 val pred_specs' = map fst pred_specs |
973 val prednames = map fst pred_specs' |
975 val prednames = map fst pred_specs' |
974 val preds = map (fn (p, ty) => Free (Binding.name_of p, ty)) pred_specs' |
976 val preds = map (fn (p, ty) => Free (Binding.name_of p, ty)) pred_specs' |
975 val tyss = map (binder_types o fastype_of) preds |
977 val tyss = map (binder_types o fastype_of) preds |
976 |
978 |
977 val (namesattrs, rules) = split_list rule_specs |
979 val (namesattrs, rules) = split_list rule_specs |
978 |
980 |
979 val (defs, lthy') = defns rules preds prednames syns tyss lthy |
981 val (defs, lthy') = defns rules preds prednames mxs tyss lthy |
980 val ind_prin = inds rules defs preds tyss lthy' |
982 val ind_prins = inds rules defs preds tyss lthy' |
981 val intro_rules = intros rules preds defs lthy' |
983 val intro_rules = intros rules preds defs lthy' |
982 |
984 |
983 val mut_name = space_implode "_" (map Binding.name_of prednames) |
985 val mut_name = space_implode "_" (map Binding.name_of prednames) |
984 val case_names = map (Binding.name_of o fst) namesattrs |
986 val case_names = map (Binding.name_of o fst) namesattrs |
985 in |
987 in |
986 lthy' |> reg_many mut_name ((@{binding "intros"}, []), intro_rules) |
988 lthy' |> reg_many mut_name ((@{binding "intros"}, []), intro_rules) |
|
989 ||>> reg_many mut_name ((@{binding "inducts"}, []), ind_prins) |
987 ||>> fold_map (reg_single1 mut_name) (namesattrs ~~ intro_rules) |
990 ||>> fold_map (reg_single1 mut_name) (namesattrs ~~ intro_rules) |
988 ||>> fold_map (reg_single2 @{binding "induct"} |
991 ||>> fold_map (reg_single2 @{binding "induct"} |
989 [Attrib.internal (K (RuleCases.case_names case_names)), |
992 [Attrib.internal (K (RuleCases.case_names case_names)), |
990 Attrib.internal (K (RuleCases.consumes 1)), |
993 Attrib.internal (K (RuleCases.consumes 1)), |
991 Attrib.internal (K (Induct.induct_pred ""))]) |
994 Attrib.internal (K (Induct.induct_pred ""))]) |
992 (prednames ~~ ind_prin) |
995 (prednames ~~ ind_prins) |
993 |> snd |
996 |> snd |
994 end*} |
997 end*} |
995 |
998 |
996 text {* |
999 text {* |
997 In Line 3 the function extracts the syntax annotations from the predicates. |
1000 In Line 3 the function extracts the syntax annotations from the predicates. |
1015 @{text [quotes] "_"}-separated list of predicate names (for example |
1018 @{text [quotes] "_"}-separated list of predicate names (for example |
1016 @{text "even_odd"}. Also by custom, the case names in intuction |
1019 @{text "even_odd"}. Also by custom, the case names in intuction |
1017 proofs correspond to the names of the introduction rules. These |
1020 proofs correspond to the names of the introduction rules. These |
1018 are generated in Line 16. |
1021 are generated in Line 16. |
1019 |
1022 |
1020 Line 18 now adds to @{text "lthy'"} all the introduction rules |
1023 Lines 18 and 19 now add to @{text "lthy'"} all the introduction rules |
1021 under the name @{text "mut_name.intros"} (see previous paragraph). |
1024 und induction principles under the name @{text "mut_name.intros"} and |
1022 Line 19 add further every introduction rule under its own name |
1025 @{text "mut_name.inducts"}, respectively (see previous paragraph). |
|
1026 |
|
1027 Line 20 add further every introduction rule under its own name |
1023 (given by the user).\footnote{FIXME: what happens if the user did not give |
1028 (given by the user).\footnote{FIXME: what happens if the user did not give |
1024 any name.} Line 20 registers the induction principles. For this we have |
1029 any name.} Line 21 registers the induction principles. For this we have |
1025 to use some specific attributes. The first @{ML "case_names" in RuleCases} |
1030 to use some specific attributes. The first @{ML "case_names" in RuleCases} |
1026 corresponds to the case names that are used by Isar to reference the proof |
1031 corresponds to the case names that are used by Isar to reference the proof |
1027 obligations in the induction. The second @{ML "consumes 1" in RuleCases} |
1032 obligations in the induction. The second @{ML "consumes 1" in RuleCases} |
1028 indicates that the first premise of the induction principle (namely |
1033 indicates that the first premise of the induction principle (namely |
1029 the predicate over which the induction proceeds) is eliminated. |
1034 the predicate over which the induction proceeds) is eliminated. |
1030 |
1035 |
1031 This completes all the code and fits in with the ``front end'' described |
1036 This completes all the code and fits in with the ``front end'' described |
1032 in Section~\ref{sec:interface}.\footnote{FIXME: Describe @{ML Induct.induct_pred}. Why the mut-name? |
1037 in Section~\ref{sec:interface}.\footnote{FIXME: Describe @{ML Induct.induct_pred}. |
|
1038 Why the mut-name? |
1033 What does @{ML Binding.qualify} do?} |
1039 What does @{ML Binding.qualify} do?} |
1034 *} |
1040 *} |
1035 (*<*)end(*>*) |
1041 (*<*)end(*>*) |