118 ML-file should not contain any \isacommand{use} itself. Otherwise Isabelle |
118 ML-file should not contain any \isacommand{use} itself. Otherwise Isabelle |
119 is unable to record all file dependencies, which is a nuisance if you have |
119 is unable to record all file dependencies, which is a nuisance if you have |
120 to track down errors. |
120 to track down errors. |
121 *} |
121 *} |
122 |
122 |
123 section {* Debugging and Printing\label{sec:printing} *} |
123 section {* Printing and Debugging\label{sec:printing} *} |
124 |
124 |
125 text {* |
125 text {* |
126 During development you might find it necessary to inspect some data in your |
126 During development you might find it necessary to inspect some data in your |
127 code. This can be done in a ``quick-and-dirty'' fashion using the function |
127 code. This can be done in a ``quick-and-dirty'' fashion using the function |
128 @{ML_ind "writeln"}. For example |
128 @{ML_ind "writeln"}. For example |
209 Most often you want to inspect data of Isabelle's most basic data |
209 Most often you want to inspect data of Isabelle's most basic data |
210 structures, namely @{ML_type term}, @{ML_type cterm} and @{ML_type |
210 structures, namely @{ML_type term}, @{ML_type cterm} and @{ML_type |
211 thm}. Isabelle contains elaborate pretty-printing functions for printing |
211 thm}. Isabelle contains elaborate pretty-printing functions for printing |
212 them (see Section \ref{sec:pretty}), but for quick-and-dirty solutions they |
212 them (see Section \ref{sec:pretty}), but for quick-and-dirty solutions they |
213 are a bit unwieldy. One way to transform a term into a string is to use the |
213 are a bit unwieldy. One way to transform a term into a string is to use the |
214 function @{ML_ind string_of_term in Syntax} in structure @{ML_struct |
214 function @{ML_ind string_of_term in Syntax} in the structure @{ML_struct |
215 Syntax}, which we bind for more convenience to the toplevel. |
215 Syntax}, which we bind for more convenience to the toplevel. |
216 *} |
216 *} |
217 |
217 |
218 ML{*val string_of_term = Syntax.string_of_term*} |
218 ML{*val string_of_term = Syntax.string_of_term*} |
219 |
219 |
633 When using combinators for writing functions in waterfall fashion, it is |
633 When using combinators for writing functions in waterfall fashion, it is |
634 sometimes necessary to do some ``plumbing'' in order to fit functions |
634 sometimes necessary to do some ``plumbing'' in order to fit functions |
635 together. We have already seen such plumbing in the function @{ML |
635 together. We have already seen such plumbing in the function @{ML |
636 apply_fresh_args}, where @{ML curry} is needed for making the function @{ML |
636 apply_fresh_args}, where @{ML curry} is needed for making the function @{ML |
637 list_comb} that works over pairs to fit with the combinator @{ML "|>"}. Such |
637 list_comb} that works over pairs to fit with the combinator @{ML "|>"}. Such |
638 plumbing is also needed in situations where a functions operate over lists, |
638 plumbing is also needed in situations where a function operate over lists, |
639 but one calculates only with a single element. An example is the function |
639 but one calculates only with a single element. An example is the function |
640 @{ML_ind check_terms in Syntax}, whose purpose is to type-check a list |
640 @{ML_ind check_terms in Syntax}, whose purpose is to type-check a list |
641 of terms. |
641 of terms. |
642 |
642 |
643 @{ML_response_fake [display, gray] |
643 @{ML_response_fake [display, gray] |
651 end" |
651 end" |
652 "m + n, m * n, m - n"} |
652 "m + n, m * n, m - n"} |
653 *} |
653 *} |
654 |
654 |
655 text {* |
655 text {* |
656 In this example we obtain three terms in which @{text m} and @{text n} are of |
656 In this example we obtain three terms whose variables @{text m} and @{text |
657 type @{typ "nat"}. If you have only a single term, then @{ML |
657 n} are of type @{typ "nat"}. If you have only a single term, then @{ML |
658 check_terms in Syntax} needs plumbing. This can be done with the function |
658 check_terms in Syntax} needs plumbing. This can be done with the function |
659 @{ML singleton}.\footnote{There is already a function @{ML check_term in |
659 @{ML singleton}.\footnote{There is already a function @{ML check_term in |
660 Syntax} in the Isabelle sources that is defined in terms of @{ML singleton} |
660 Syntax} in the Isabelle sources that is defined in terms of @{ML singleton} |
661 and @{ML check_terms in Syntax}.} For example |
661 and @{ML check_terms in Syntax}.} For example |
662 |
662 |
711 current theory (remember that we assumed we are inside the theory |
711 current theory (remember that we assumed we are inside the theory |
712 @{text FirstSteps}). The name of this theory can be extracted using |
712 @{text FirstSteps}). The name of this theory can be extracted using |
713 the function @{ML_ind theory_name in Context}. |
713 the function @{ML_ind theory_name in Context}. |
714 |
714 |
715 Note, however, that antiquotations are statically linked, that is their value is |
715 Note, however, that antiquotations are statically linked, that is their value is |
716 determined at ``compile-time'', not ``run-time''. For example the function |
716 determined at ``compile-time'', not at ``run-time''. For example the function |
717 *} |
717 *} |
718 |
718 |
719 ML{*fun not_current_thyname () = Context.theory_name @{theory} *} |
719 ML{*fun not_current_thyname () = Context.theory_name @{theory} *} |
720 |
720 |
721 text {* |
721 text {* |
741 ((?P \<and> ?Q) \<and> ?R) = (?P \<and> ?Q \<and> ?R)"} |
741 ((?P \<and> ?Q) \<and> ?R) = (?P \<and> ?Q \<and> ?R)"} |
742 |
742 |
743 The point of these antiquotations is that referring to theorems in this way |
743 The point of these antiquotations is that referring to theorems in this way |
744 makes your code independent from what theorems the user might have stored |
744 makes your code independent from what theorems the user might have stored |
745 under this name (this becomes especially important when you deal with |
745 under this name (this becomes especially important when you deal with |
746 theorem lists; see Section \ref{sec:attributes}). |
746 theorem lists; see Section \ref{sec:storing}). |
747 |
747 |
748 You can also refer to the current simpset via an antiquotation. To illustrate |
748 You can also refer to the current simpset via an antiquotation. To illustrate |
749 this we implement the function that extracts the theorem names stored in a |
749 this we implement the function that extracts the theorem names stored in a |
750 simpset. |
750 simpset. |
751 *} |
751 *} |
782 |
782 |
783 An example where a qualified name is needed is the function |
783 An example where a qualified name is needed is the function |
784 @{ML_ind define in LocalTheory}. This function is used below to define |
784 @{ML_ind define in LocalTheory}. This function is used below to define |
785 the constant @{term "TrueConj"} as the conjunction @{term "True \<and> True"}. |
785 the constant @{term "TrueConj"} as the conjunction @{term "True \<and> True"}. |
786 *} |
786 *} |
787 |
787 |
788 local_setup %gray {* |
788 local_setup %gray {* |
789 LocalTheory.define Thm.internalK |
789 LocalTheory.define Thm.internalK |
790 ((@{binding "TrueConj"}, NoSyn), |
790 ((@{binding "TrueConj"}, NoSyn), |
791 (Attrib.empty_binding, @{term "True \<and> True"})) #> snd *} |
791 (Attrib.empty_binding, @{term "True \<and> True"})) #> snd *} |
792 |
792 |
796 \begin{isabelle} |
796 \begin{isabelle} |
797 \isacommand{thm}~@{text "TrueConj_def"}\\ |
797 \isacommand{thm}~@{text "TrueConj_def"}\\ |
798 @{text "> "}~@{thm TrueConj_def} |
798 @{text "> "}~@{thm TrueConj_def} |
799 \end{isabelle} |
799 \end{isabelle} |
800 |
800 |
|
801 \begin{readmore} |
|
802 The basic operations on bindings are implemented in |
|
803 @{ML_file "Pure/General/binding.ML"}. |
|
804 \end{readmore} |
|
805 |
801 \footnote{\bf FIXME give a better example why bindings are important; maybe |
806 \footnote{\bf FIXME give a better example why bindings are important; maybe |
802 give a pointer to \isacommand{local\_setup}; if not, then explain |
807 give a pointer to \isacommand{local\_setup}; if not, then explain |
803 why @{ML snd} is needed.} |
808 why @{ML snd} is needed.} |
|
809 \footnote{\bf FIXME: There should probably a separate section on binding, long-names |
|
810 and sign.} |
804 |
811 |
805 It is also possible to define your own antiquotations. But you should |
812 It is also possible to define your own antiquotations. But you should |
806 exercise care when introducing new ones, as they can also make your code |
813 exercise care when introducing new ones, as they can also make your code |
807 also difficult to read. In the next chapter we will see how the (build in) |
814 also difficult to read. In the next chapter we will see how the (build in) |
808 antiquotation @{text "@{term \<dots>}"} can be used to construct terms. A |
815 antiquotation @{text "@{term \<dots>}"} can be used to construct terms. A |
1049 "WrongRefData.get @{theory}" |
1057 "WrongRefData.get @{theory}" |
1050 "ref [1, 1]"} |
1058 "ref [1, 1]"} |
1051 |
1059 |
1052 Now imagine how often you go backwards and forwards in your proof scripts. |
1060 Now imagine how often you go backwards and forwards in your proof scripts. |
1053 By using references in Isabelle code, you are bound to cause all |
1061 By using references in Isabelle code, you are bound to cause all |
1054 hell to break lose. Therefore observe the coding convention: |
1062 hell to break loose. Therefore observe the coding convention: |
1055 Do not use references for storing data! |
1063 Do not use references for storing data! |
1056 |
1064 |
1057 \begin{readmore} |
1065 \begin{readmore} |
1058 The functors for data storage are defined in @{ML_file "Pure/context.ML"}. |
1066 The functors for data storage are defined in @{ML_file "Pure/context.ML"}. |
1059 Isabelle contains implementations of several container data structures, |
1067 Isabelle contains implementations of several container data structures, |
1060 including association lists in @{ML_file "Pure/General/alist.ML"}, |
1068 including association lists in @{ML_file "Pure/General/alist.ML"}, |
1061 directed graphs in @{ML_file "Pure/General/graph.ML"}. and |
1069 directed graphs in @{ML_file "Pure/General/graph.ML"}. and |
1062 tables and symtables in @{ML_file "Pure/General/table.ML"}. |
1070 tables and symtables in @{ML_file "Pure/General/table.ML"}. |
1063 \end{readmore} |
|
1064 |
|
1065 A special instance of the data storage mechanism described above are |
|
1066 configuration values. They are used to enable users to configure tools |
|
1067 without having to resort to the ML-level (and also to avoid |
|
1068 references). Assume you want the user to control three values, say @{text |
|
1069 bval} containing a boolean, @{text ival} containing an integer and @{text |
|
1070 sval} containing a string. These values can be declared by |
|
1071 *} |
|
1072 |
|
1073 ML{*val (bval, setup_bval) = Attrib.config_bool "bval" false |
|
1074 val (ival, setup_ival) = Attrib.config_int "ival" 0 |
|
1075 val (sval, setup_sval) = Attrib.config_string "sval" "some string" *} |
|
1076 |
|
1077 text {* |
|
1078 where each value needs to be given a default. To enable these values, they need to |
|
1079 be set up with |
|
1080 *} |
|
1081 |
|
1082 setup %gray {* |
|
1083 setup_bval #> |
|
1084 setup_ival |
|
1085 *} |
|
1086 |
|
1087 text {* |
|
1088 The user can now manipulate the values from the user-level of Isabelle |
|
1089 with the command |
|
1090 *} |
|
1091 |
|
1092 declare [[bval = true, ival = 3]] |
|
1093 |
|
1094 text {* |
|
1095 On the ML-level these values can be retrieved using the |
|
1096 function @{ML Config.get}. |
|
1097 |
|
1098 @{ML_response [display,gray] "Config.get @{context} bval" "true"} |
|
1099 |
|
1100 \begin{readmore} |
|
1101 For more information about configuration values see |
|
1102 @{ML_file "Pure/Isar/attrib.ML"} and @{ML_file "Pure/config.ML"}. |
|
1103 \end{readmore} |
1071 \end{readmore} |
1104 |
1072 |
1105 Storing data in a proof context is done in a similar fashion. The |
1073 Storing data in a proof context is done in a similar fashion. The |
1106 corresponding functor is @{ML_funct_ind ProofDataFun}. With the |
1074 corresponding functor is @{ML_funct_ind ProofDataFun}. With the |
1107 following code we can store a list of terms in a proof context. |
1075 following code we can store a list of terms in a proof context. |
1153 Isabelle code, although the ``context flow'' is usually only linear. |
1121 Isabelle code, although the ``context flow'' is usually only linear. |
1154 Note also that the calculation above has no effect on the underlying |
1122 Note also that the calculation above has no effect on the underlying |
1155 theory. Once we throw away the contexts, we have no access to their |
1123 theory. Once we throw away the contexts, we have no access to their |
1156 associated data. This is different to theories, where the command |
1124 associated data. This is different to theories, where the command |
1157 \isacommand{setup} registers the data with the current and future |
1125 \isacommand{setup} registers the data with the current and future |
1158 theories, and therefore can access the data potentially indefinitely. |
1126 theories, and therefore can access the data potentially |
1159 *} |
1127 indefinitely.\footnote{\bf FIXME: check this; it seems that is in |
1160 |
1128 conflict with the statements below.} |
|
1129 |
|
1130 \footnote{\bf FIXME: Say something about generic contexts.} |
|
1131 |
|
1132 There are two special instances of the data storage mechanism described |
|
1133 above. The first instance are named theorem lists. Since storing theorems in a list |
|
1134 is such a common task, there is the special functor @{ML_funct_ind Named_Thms}. |
|
1135 To obtain a named theorem list, you just declare |
|
1136 *} |
|
1137 |
|
1138 ML{*structure FooRules = Named_Thms |
|
1139 (val name = "foo" |
|
1140 val description = "Theorems for foo") *} |
|
1141 |
|
1142 text {* |
|
1143 and set up the @{ML_struct FooRules} with the command |
|
1144 *} |
|
1145 |
|
1146 setup %gray {* FooRules.setup *} |
|
1147 |
|
1148 text {* |
|
1149 This code declares a data container where the theorems are stored, |
|
1150 an attribute @{text foo} (with the @{text add} and @{text del} options |
|
1151 for adding and deleting theorems) and an internal ML-interface to retrieve and |
|
1152 modify the theorems. |
|
1153 |
|
1154 Furthermore, the facts are made available on the user-level under the dynamic |
|
1155 fact name @{text foo}. For example you can declare three lemmas to be of the kind |
|
1156 @{text foo} by: |
|
1157 *} |
|
1158 |
|
1159 lemma rule1[foo]: "A" sorry |
|
1160 lemma rule2[foo]: "B" sorry |
|
1161 lemma rule3[foo]: "C" sorry |
|
1162 |
|
1163 text {* and undeclare the first one by: *} |
|
1164 |
|
1165 declare rule1[foo del] |
|
1166 |
|
1167 text {* and query the remaining ones with: |
|
1168 |
|
1169 \begin{isabelle} |
|
1170 \isacommand{thm}~@{text "foo"}\\ |
|
1171 @{text "> ?C"}\\ |
|
1172 @{text "> ?B"} |
|
1173 \end{isabelle} |
|
1174 |
|
1175 On the ML-level, we can add theorems to the list with @{ML FooRules.add_thm}: |
|
1176 *} |
|
1177 |
|
1178 setup %gray {* |
|
1179 Context.theory_map (FooRules.add_thm @{thm TrueI}) |
|
1180 *} |
|
1181 |
|
1182 text {* |
|
1183 The rules in the list can be retrieved using the function |
|
1184 @{ML FooRules.get}: |
|
1185 |
|
1186 @{ML_response_fake [display,gray] "FooRules.get @{context}" "[\"True\", \"?C\",\"?B\"]"} |
|
1187 |
|
1188 \begin{readmore} |
|
1189 For more information see @{ML_file "Pure/Tools/named_thms.ML"}. |
|
1190 \end{readmore} |
|
1191 |
|
1192 The second special instance of the data storage mechanism are configuration |
|
1193 values. They are used to enable users to configure tools without having to |
|
1194 resort to the ML-level (and also to avoid references). Assume you want the |
|
1195 user to control three values, say @{text bval} containing a boolean, @{text |
|
1196 ival} containing an integer and @{text sval} containing a string. These |
|
1197 values can be declared by |
|
1198 *} |
|
1199 |
|
1200 ML{*val (bval, setup_bval) = Attrib.config_bool "bval" false |
|
1201 val (ival, setup_ival) = Attrib.config_int "ival" 0 |
|
1202 val (sval, setup_sval) = Attrib.config_string "sval" "some string" *} |
|
1203 |
|
1204 text {* |
|
1205 where each value needs to be given a default. To enable these values, they need to |
|
1206 be set up with |
|
1207 *} |
|
1208 |
|
1209 setup %gray {* |
|
1210 setup_bval #> |
|
1211 setup_ival |
|
1212 *} |
|
1213 |
|
1214 text {* |
|
1215 The user can now manipulate the values from the user-level of Isabelle |
|
1216 with the command |
|
1217 *} |
|
1218 |
|
1219 declare [[bval = true, ival = 3]] |
|
1220 |
|
1221 text {* |
|
1222 On the ML-level these values can be retrieved using the |
|
1223 function @{ML Config.get}. |
|
1224 |
|
1225 @{ML_response [display,gray] "Config.get @{context} bval" "true"} |
|
1226 |
|
1227 \begin{readmore} |
|
1228 For more information about configuration values see |
|
1229 @{ML_file "Pure/Isar/attrib.ML"} and @{ML_file "Pure/config.ML"}. |
|
1230 \end{readmore} |
|
1231 *} |
1161 |
1232 |
1162 |
1233 |
1163 (**************************************************) |
1234 (**************************************************) |
1164 (* bak *) |
1235 (* bak *) |
1165 (**************************************************) |
1236 (**************************************************) |