ProgTutorial/FirstSteps.thy
changeset 207 d3cd633e8240
parent 204 3857d987576a
child 210 db8e302f44c8
equal deleted inserted replaced
206:096776f180fc 207:d3cd633e8240
   130 
   130 
   131   (FIXME @{ML Toplevel.debug} @{ML Toplevel.profiling})
   131   (FIXME @{ML Toplevel.debug} @{ML Toplevel.profiling})
   132 *}
   132 *}
   133 
   133 
   134 (*
   134 (*
   135 ML {* set Toplevel.debug *}
   135 ML {* reset Toplevel.debug *}
   136 
   136 
   137 ML {*
   137 ML {* fun dodgy_fun () = (raise TYPE ("",[],[]); 1) *}
   138 fun dodgy_fun () = (raise (ERROR "bar"); 1) 
   138 
   139 *}
   139 ML {* fun innocent () = dodgy_fun () *}
   140 
   140 ML {* exception_trace (fn () => cterm_of @{theory} (Bound 0)) *}
   141 ML {* fun f1 () = dodgy_fun () *}
   141 ML {* exception_trace (fn () => innocent ()) *}
   142 
   142 
   143 ML {* f1 () *}
   143 ML {* Toplevel.program (fn () => cterm_of @{theory} (Bound 0)) *}
       
   144 
       
   145 ML {* Toplevel.program (fn () => innocent ()) *}
   144 *)
   146 *)
   145 
   147 
   146 text {*
   148 text {*
   147   Most often you want to inspect data of type @{ML_type term}, @{ML_type cterm} 
   149   Most often you want to inspect data of type @{ML_type term}, @{ML_type cterm} 
   148   or @{ML_type thm}. Isabelle contains elaborate pretty-printing functions for printing them, 
   150   or @{ML_type thm}. Isabelle contains elaborate pretty-printing functions for printing them, 
   205 
   207 
   206 fun str_of_thm_no_vars ctxt thm =
   208 fun str_of_thm_no_vars ctxt thm =
   207   str_of_cterm ctxt (#prop (crep_thm (no_vars ctxt thm)))*}
   209   str_of_cterm ctxt (#prop (crep_thm (no_vars ctxt thm)))*}
   208 
   210 
   209 text {* 
   211 text {* 
   210   Theorem @{thm [source] conjI} looks now as follows:
   212   Theorem @{thm [source] conjI} is now printed as follows:
   211 
   213 
   212   @{ML_response_fake [display, gray]
   214   @{ML_response_fake [display, gray]
   213   "warning (str_of_thm_no_vars @{context} @{thm conjI})"
   215   "warning (str_of_thm_no_vars @{context} @{thm conjI})"
   214   "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> P \<and> Q"}
   216   "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> P \<and> Q"}
   215   
   217   
   518 local_setup %gray {* 
   520 local_setup %gray {* 
   519   snd o LocalTheory.define Thm.internalK 
   521   snd o LocalTheory.define Thm.internalK 
   520     ((@{binding "TrueConj"}, NoSyn), 
   522     ((@{binding "TrueConj"}, NoSyn), 
   521      (Attrib.empty_binding, @{term "True \<and> True"})) *}
   523      (Attrib.empty_binding, @{term "True \<and> True"})) *}
   522 
   524 
   523 <<<<<<< local
       
   524 text {* 
   525 text {* 
   525   Now querying the definition you obtain:
   526   Now querying the definition you obtain:
   526 
   527 
   527   \begin{isabelle}
   528   \begin{isabelle}
   528   \isacommand{thm}~@{text "TrueConj_def"}\\
   529   \isacommand{thm}~@{text "TrueConj_def"}\\
   558   @{ML_response [display,gray] 
   559   @{ML_response [display,gray] 
   559 "@{term \"(a::nat) + b = c\"}" 
   560 "@{term \"(a::nat) + b = c\"}" 
   560 "Const (\"op =\", \<dots>) $ 
   561 "Const (\"op =\", \<dots>) $ 
   561   (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"}
   562   (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"}
   562 
   563 
   563   will show the term @{term "(a::nat) + b = c"}, but printed using an internal
   564   will show the term @{term "(a::nat) + b = c"}, but printed using the internal
   564   representation corresponding to the data type @{ML_type "term"}.
   565   representation corresponding to the data type @{ML_type "term"}.
   565   
   566   
   566   This internal representation uses the usual de Bruijn index mechanism---where
   567   This internal representation uses the usual de Bruijn index mechanism---where
   567   bound variables are represented by the constructor @{ML Bound}.  The index in
   568   bound variables are represented by the constructor @{ML Bound}.  The index in
   568   @{ML Bound} refers to the number of Abstractions (@{ML Abs}) we have to skip
   569   @{ML Bound} refers to the number of Abstractions (@{ML Abs}) we have to skip
   933   you obtain the certified type for the Isabelle type @{typ "nat \<Rightarrow> bool"} on 
   934   you obtain the certified type for the Isabelle type @{typ "nat \<Rightarrow> bool"} on 
   934   the ML-level as follows:
   935   the ML-level as follows:
   935 
   936 
   936   @{ML_response_fake [display,gray]
   937   @{ML_response_fake [display,gray]
   937   "ctyp_of @{theory} (@{typ nat} --> @{typ bool})"
   938   "ctyp_of @{theory} (@{typ nat} --> @{typ bool})"
       
   939   "nat \<Rightarrow> bool"}
       
   940 
       
   941   or with the antiquotation:
       
   942 
       
   943   @{ML_response_fake [display,gray]
       
   944   "@{ctyp \"nat \<Rightarrow> bool\"}"
   938   "nat \<Rightarrow> bool"}
   945   "nat \<Rightarrow> bool"}
   939 
   946 
   940   \begin{readmore}
   947   \begin{readmore}
   941   For functions related to @{ML_type cterm}s and @{ML_type ctyp}s see 
   948   For functions related to @{ML_type cterm}s and @{ML_type ctyp}s see 
   942   the file @{ML_file "Pure/thm.ML"}.
   949   the file @{ML_file "Pure/thm.ML"}.
  1070   For the functions @{text "assume"}, @{text "forall_elim"} etc 
  1077   For the functions @{text "assume"}, @{text "forall_elim"} etc 
  1071   see \isccite{sec:thms}. The basic functions for theorems are defined in
  1078   see \isccite{sec:thms}. The basic functions for theorems are defined in
  1072   @{ML_file "Pure/thm.ML"}. 
  1079   @{ML_file "Pure/thm.ML"}. 
  1073   \end{readmore}
  1080   \end{readmore}
  1074 
  1081 
  1075   (FIXME: handy functions working on theorems; how to add case-names to goal 
  1082   (FIXME: handy functions working on theorems, like @{ML ObjectLogic.rulify} and so on) 
  1076   states - maybe in the next section)
  1083 
       
  1084   (FIXME how to add case-names to goal states - maybe in the 
       
  1085   next section)
  1077 *}
  1086 *}
  1078 
  1087 
  1079 section {* Theorem Attributes *}
  1088 section {* Theorem Attributes *}
  1080 
  1089 
  1081 text {*
  1090 text {*
  1097   @{text "> HOL.elim:  declaration of Classical elimination rule"}\\
  1106   @{text "> HOL.elim:  declaration of Classical elimination rule"}\\
  1098   @{text "> \<dots>"}
  1107   @{text "> \<dots>"}
  1099   \end{isabelle}
  1108   \end{isabelle}
  1100   
  1109   
  1101   The theorem attributes fall roughly into two categories: the first category manipulates
  1110   The theorem attributes fall roughly into two categories: the first category manipulates
  1102   the proved theorem (like @{text "[symmetric]"} and @{text "[THEN \<dots>]"}), and the second
  1111   the proved theorem (for example @{text "[symmetric]"} and @{text "[THEN \<dots>]"}), and the second
  1103   stores the proved theorem somewhere as data (like @{text "[simp]"}, which adds
  1112   stores the proved theorem somewhere as data (for example @{text "[simp]"}, which adds
  1104   the theorem to the current simpset).
  1113   the theorem to the current simpset).
  1105 
  1114 
  1106   To explain how to write your own attribute, let us start with an extremely simple 
  1115   To explain how to write your own attribute, let us start with an extremely simple 
  1107   version of the attribute @{text "[symmetric]"}. The purpose of this attribute is
  1116   version of the attribute @{text "[symmetric]"}. The purpose of this attribute is
  1108   to produce the ``symmetric'' version of an equation. The main function behind 
  1117   to produce the ``symmetric'' version of an equation. The main function behind 
  1112 ML{*val my_symmetric = Thm.rule_attribute (fn _ => fn thm => thm RS @{thm sym})*}
  1121 ML{*val my_symmetric = Thm.rule_attribute (fn _ => fn thm => thm RS @{thm sym})*}
  1113 
  1122 
  1114 text {* 
  1123 text {* 
  1115   where the function @{ML "Thm.rule_attribute"} expects a function taking a 
  1124   where the function @{ML "Thm.rule_attribute"} expects a function taking a 
  1116   context (which we ignore in the code above) and a theorem (@{text thm}), and 
  1125   context (which we ignore in the code above) and a theorem (@{text thm}), and 
  1117   returns another theorem (namely @{text thm} resolved with the lemma 
  1126   returns another theorem (namely @{text thm} resolved with the theorem 
  1118   @{thm [source] sym}: @{thm sym[no_vars]}). The function @{ML "Thm.rule_attribute"} then returns 
  1127   @{thm [source] sym}: @{thm sym[no_vars]}).\footnote{The function @{ML RS} is explained
       
  1128   later on in Section~\ref{sec:simpletacs}.} The function 
       
  1129   @{ML "Thm.rule_attribute"} then returns 
  1119   an attribute.
  1130   an attribute.
  1120 
  1131 
  1121   Before we can use the attribute, we need to set it up. This can be done
  1132   Before we can use the attribute, we need to set it up. This can be done
  1122   using the Isabelle command \isacommand{attribute\_setup} as follows:
  1133   using the Isabelle command \isacommand{attribute\_setup} as follows:
  1123 *}
  1134 *}
  1124 
  1135 
  1125 attribute_setup %gray my_sym = {* Scan.succeed my_symmetric *} 
  1136 attribute_setup %gray my_sym = {* Scan.succeed my_symmetric *} 
  1126   "applying the sym rule"
  1137   "applying the sym rule"
  1127 
  1138 
  1128 text {*
  1139 text {*
  1129   The attribute does not expect any further arguments (unlike @{text "[THEN
  1140   Inside the @{text "\<verbopen> \<dots> \<verbclose>"}, we have to specify a parser
  1130   \<dots>]"}, for example). Therefore
  1141   for the theorem attribute. Since the attribute does not expect any further 
  1131   we use the parser @{ML Scan.succeed}. Later on we will also consider
  1142   arguments (unlike @{text "[THEN \<dots>]"}, for example), we use the parser @{ML
  1132   attributes taking further arguments. An example for the attribute @{text
  1143   Scan.succeed}. Later on we will also consider attributes taking further
  1133   "[my_sym]"} is the proof
  1144   arguments. An example for the attribute @{text "[my_sym]"} is the proof
  1134 *} 
  1145 *} 
  1135 
  1146 
  1136 lemma test[my_sym]: "2 = Suc (Suc 0)" by simp
  1147 lemma test[my_sym]: "2 = Suc (Suc 0)" by simp
  1137 
  1148 
  1138 text {*
  1149 text {*
  1150   \isacommand{thm}~@{text "test[my_sym]"}\\
  1161   \isacommand{thm}~@{text "test[my_sym]"}\\
  1151   @{text "> "}~@{thm test[my_sym]}
  1162   @{text "> "}~@{thm test[my_sym]}
  1152   \end{isabelle}
  1163   \end{isabelle}
  1153 
  1164 
  1154   As an example of a slightly more complicated theorem attribute, we implement 
  1165   As an example of a slightly more complicated theorem attribute, we implement 
  1155   our version of @{text "[THEN \<dots>]"}. This attribute will take a list of theorems
  1166   our own version of @{text "[THEN \<dots>]"}. This attribute will take a list of theorems
  1156   as argument and resolve the proved theorem with this list (one theorem 
  1167   as argument and resolve the proved theorem with this list (one theorem 
  1157   after another). The code for this attribute is
  1168   after another). The code for this attribute is
  1158 *}
  1169 *}
  1159 
  1170 
  1160 ML{*fun MY_THEN thms = 
  1171 ML{*fun MY_THEN thms = 
  1161   Thm.rule_attribute (fn _ => fn thm => foldl ((op RS) o swap) thm thms)*}
  1172   Thm.rule_attribute (fn _ => fn thm => foldl ((op RS) o swap) thm thms)*}
  1162 
  1173 
  1163 text {* 
  1174 text {* 
  1164   where @{ML swap} swaps the components of a pair (@{ML RS} is explained
  1175   where @{ML swap} swaps the components of a pair. The setup of this theorem
  1165   later on in Section~\ref{sec:simpletacs}). The setup of this theorem
       
  1166   attribute uses the parser @{ML Attrib.thms}, which parses a list of
  1176   attribute uses the parser @{ML Attrib.thms}, which parses a list of
  1167   theorems. 
  1177   theorems. 
  1168 *}
  1178 *}
  1169 
  1179 
  1170 attribute_setup %gray MY_THEN = {* Attrib.thms >> MY_THEN *} 
  1180 attribute_setup %gray MY_THEN = {* Attrib.thms >> MY_THEN *} 
  1214 *}
  1224 *}
  1215 
  1225 
  1216 ML{*val my_thms = ref ([] : thm list)*}
  1226 ML{*val my_thms = ref ([] : thm list)*}
  1217 
  1227 
  1218 text {* 
  1228 text {* 
  1219   A word of warning: such references must not be used in any code that
  1229   The purpose of this reference is that we are going to add and delete theorems
  1220   is meant to be more than just for testing purposes! Here it is only used 
  1230   to the referenced list. However, a word of warning: such references must not 
  1221   to illustrate matters. We will show later how to store data properly without 
  1231   be used in any code that is meant to be more than just for testing purposes! 
  1222   using references.
  1232   Here it is only used to illustrate matters. We will show later how to store 
       
  1233   data properly without using references.
  1223  
  1234  
  1224   The function @{ML Thm.declaration_attribute} expects us to 
  1235   We need to provide two functions that add and delete theorems from this list. 
  1225   provide two functions that add and delete theorems from this list. 
       
  1226   For this we use the two functions:
  1236   For this we use the two functions:
  1227 *}
  1237 *}
  1228 
  1238 
  1229 ML{*fun my_thms_add thm ctxt =
  1239 ML{*fun my_thm_add thm ctxt =
  1230   (my_thms := Thm.add_thm thm (!my_thms); ctxt)
  1240   (my_thms := Thm.add_thm thm (!my_thms); ctxt)
  1231 
  1241 
  1232 fun my_thms_del thm ctxt =
  1242 fun my_thm_del thm ctxt =
  1233   (my_thms := Thm.del_thm thm (!my_thms); ctxt)*}
  1243   (my_thms := Thm.del_thm thm (!my_thms); ctxt)*}
  1234 
  1244 
  1235 text {*
  1245 text {*
  1236   These functions take a theorem and a context and, for what we are explaining
  1246   These functions take a theorem and a context and, for what we are explaining
  1237   here it is sufficient that they just return the context unchanged. They change
  1247   here it is sufficient that they just return the context unchanged. They change
  1240   Thm.del_thm} deletes one (both functions use the predicate @{ML
  1250   Thm.del_thm} deletes one (both functions use the predicate @{ML
  1241   Thm.eq_thm_prop}, which compares theorems according to their proved
  1251   Thm.eq_thm_prop}, which compares theorems according to their proved
  1242   propositions modulo alpha-equivalence).
  1252   propositions modulo alpha-equivalence).
  1243 
  1253 
  1244 
  1254 
  1245   You can turn functions @{ML my_thms_add} and @{ML my_thms_del} into 
  1255   You can turn functions @{ML my_thm_add} and @{ML my_thm_del} into 
  1246   attributes with the code
  1256   attributes with the code
  1247 *}
  1257 *}
  1248 
  1258 
  1249 ML{*val my_add = Thm.declaration_attribute my_thms_add
  1259 ML{*val my_add = Thm.declaration_attribute my_thm_add
  1250 val my_del = Thm.declaration_attribute my_thms_del *}
  1260 val my_del = Thm.declaration_attribute my_thm_del *}
  1251 
  1261 
  1252 text {* 
  1262 text {* 
  1253   and set up the attributes as follows
  1263   and set up the attributes as follows
  1254 *}
  1264 *}
  1255 
  1265 
  1256 attribute_setup %gray my_thms = {* Attrib.add_del my_add my_del *} 
  1266 attribute_setup %gray my_thms = {* Attrib.add_del my_add my_del *} 
  1257   "maintaining a list of my_thms" 
  1267   "maintaining a list of my_thms - rough test only!" 
  1258 
  1268 
  1259 text {*
  1269 text {*
  1260   The parser @{ML Attrib.add_del} is a predefined parser for 
  1270   The parser @{ML Attrib.add_del} is a pre-defined parser for 
  1261   adding and deleting lemmas. Now if you prove the next lemma 
  1271   adding and deleting lemmas. Now if you prove the next lemma 
  1262   and attach the attribute 
  1272   and attach to it the attribute @{text "[my_thms]"}
  1263   @{text "[my_thms]"}
       
  1264 *}
  1273 *}
  1265 
  1274 
  1266 lemma trueI_2[my_thms]: "True" by simp
  1275 lemma trueI_2[my_thms]: "True" by simp
  1267 
  1276 
  1268 text {*
  1277 text {*
  1272   "!my_thms" "[\"True\"]"}
  1281   "!my_thms" "[\"True\"]"}
  1273 
  1282 
  1274   You can also add theorems using the command \isacommand{declare}.
  1283   You can also add theorems using the command \isacommand{declare}.
  1275 *}
  1284 *}
  1276 
  1285 
  1277 declare test[my_thms] trueI_2[my_thms add]
  1286 declare test[my_thms] trueI_2[my_thms add] 
  1278 
  1287 
  1279 text {*
  1288 text {*
  1280   The @{text "add"} is the default operation and does not need
  1289   With this attribute, the @{text "add"} operation is the default and does 
  1281   to be explicitly given. These two declarations will cause the 
  1290   not need to be explicitly given. These three declarations will cause the 
  1282   theorem list to be updated as:
  1291   theorem list to be updated as:
  1283 
  1292 
  1284   @{ML_response_fake [display,gray]
  1293   @{ML_response_fake [display,gray]
  1285   "!my_thms"
  1294   "!my_thms"
  1286   "[\"True\", \"Suc (Suc 0) = 2\"]"}
  1295   "[\"True\", \"Suc (Suc 0) = 2\"]"}
  1302   but there can be any number of them. We just have to change the parser for reading
  1311   but there can be any number of them. We just have to change the parser for reading
  1303   the arguments accordingly. 
  1312   the arguments accordingly. 
  1304 
  1313 
  1305   However, as said at the beginning of this example, using references for storing theorems is
  1314   However, as said at the beginning of this example, using references for storing theorems is
  1306   \emph{not} the received way of doing such things. The received way is to 
  1315   \emph{not} the received way of doing such things. The received way is to 
  1307   start a ``data slot'', below called @{text MyThmsData}, by using the functor 
  1316   start a ``data slot'', below called @{text MyThmsData}, generated by the functor 
  1308   @{text GenericDataFun}:
  1317   @{text GenericDataFun}:
  1309 *}
  1318 *}
  1310 
  1319 
  1311 ML {*structure MyThmsData = GenericDataFun
  1320 ML {*structure MyThmsData = GenericDataFun
  1312  (type T = thm list
  1321  (type T = thm list
  1313   val empty = []
  1322   val empty = []
  1314   val extend = I
  1323   val extend = I
  1315   fun merge _ = Thm.merge_thms) *}
  1324   fun merge _ = Thm.merge_thms) *}
  1316 
  1325 
  1317 text {*
  1326 text {*
  1318   To use this data slot, you only have to change @{ML my_thms_add} and
  1327   The type @{text "T"} of this data slot is @{ML_type "thm list"}.\footnote{FIXME: give a pointer
  1319   @{ML my_thms_del} to:
  1328   to where data slots are explained properly.}
  1320 *}
  1329   To use this data slot, you only have to change @{ML my_thm_add} and
  1321 
  1330   @{ML my_thm_del} to:
  1322 ML{*val thm_add = MyThmsData.map o Thm.add_thm
  1331 *}
  1323 val thm_del = MyThmsData.map o Thm.del_thm*}
  1332 
       
  1333 ML{*val my_thm_add = MyThmsData.map o Thm.add_thm
       
  1334 val my_thm_del = MyThmsData.map o Thm.del_thm*}
  1324 
  1335 
  1325 text {*
  1336 text {*
  1326   where @{ML MyThmsData.map} updates the data appropriately. The
  1337   where @{ML MyThmsData.map} updates the data appropriately. The
  1327   corresponding theorem addtributes are
  1338   corresponding theorem addtributes are
  1328 *}
  1339 *}
  1329 
  1340 
  1330 ML{*val add = Thm.declaration_attribute thm_add
  1341 ML{*val my_add = Thm.declaration_attribute my_thm_add
  1331 val del = Thm.declaration_attribute thm_del *}
  1342 val my_del = Thm.declaration_attribute my_thm_del *}
  1332 
  1343 
  1333 text {*
  1344 text {*
  1334   and the setup is as follows
  1345   and the setup is as follows
  1335 *}
  1346 *}
  1336 
  1347 
  1337 attribute_setup %gray my_thms2 = {* Attrib.add_del add del *} 
  1348 attribute_setup %gray my_thms2 = {* Attrib.add_del my_add my_del *} 
  1338   "properly maintaining a list of my_thms"
  1349   "properly maintaining a list of my_thms"
  1339 
  1350 
  1340 text {*
  1351 text {*
  1341   Initially, the data slot is empty
  1352   Initially, the data slot is empty 
  1342 
  1353 
  1343   @{ML_response_fake [display,gray]
  1354   @{ML_response_fake [display,gray]
  1344   "MyThmsData.get (Context.Proof @{context})"
  1355   "MyThmsData.get (Context.Proof @{context})"
  1345   "[]"}
  1356   "[]"}
  1346 
  1357 
  1348 *}
  1359 *}
  1349 
  1360 
  1350 lemma three[my_thms2]: "3 = Suc (Suc (Suc 0))" by simp
  1361 lemma three[my_thms2]: "3 = Suc (Suc (Suc 0))" by simp
  1351 
  1362 
  1352 text {*
  1363 text {*
  1353   the lemma is now included
  1364   then the lemma is recorded. 
  1354 
  1365 
  1355   @{ML_response_fake [display,gray]
  1366   @{ML_response_fake [display,gray]
  1356   "MyThmsData.get (Context.Proof @{context})"
  1367   "MyThmsData.get (Context.Proof @{context})"
  1357   "[\"3 = Suc (Suc (Suc 0))\"]"}
  1368   "[\"3 = Suc (Suc (Suc 0))\"]"}
  1358 
  1369 
  1359   With @{text my_thms2} you can also nicely see why it is important to 
  1370   With theorem attribute @{text my_thms2} you can also nicely see why it 
       
  1371   is important to 
  1360   store data in a ``data slot'' and \emph{not} in a reference. Backtrack
  1372   store data in a ``data slot'' and \emph{not} in a reference. Backtrack
  1361   to the point just before the lemma @{thm [source] three} is proved and 
  1373   to the point just before the lemma @{thm [source] three} was proved and 
  1362   check the the content of @{ML_struct "MyThmsData"}: it is now again 
  1374   check the the content of @{ML_struct "MyThmsData"}: it should be empty. 
  1363   empty. The addition has been properly retracted. Now consider the proof:
  1375   The addition has been properly retracted. Now consider the proof:
  1364 *}
  1376 *}
  1365 
  1377 
  1366 lemma four[my_thms]: "4 = Suc (Suc (Suc (Suc 0)))" by simp
  1378 lemma four[my_thms]: "4 = Suc (Suc (Suc (Suc 0)))" by simp
  1367 
  1379 
  1368 text {*
  1380 text {*
  1370 
  1382 
  1371   @{ML_response_fake [display,gray]
  1383   @{ML_response_fake [display,gray]
  1372   "!my_thms"
  1384   "!my_thms"
  1373   "[\"4 = Suc (Suc (Suc (Suc 0)))\", \"True\"]"}
  1385   "[\"4 = Suc (Suc (Suc (Suc 0)))\", \"True\"]"}
  1374 
  1386 
  1375   as expected, but if we backtrack before the lemma @{thm [source] four}, the
  1387   as expected, but if you backtrack before the lemma @{thm [source] four}, the
  1376   content of @{ML my_thms} is unchanged. The backtracking mechanism
  1388   content of @{ML my_thms} is unchanged. The backtracking mechanism
  1377   of Isabelle is completely oblivious about what to do with references!
  1389   of Isabelle is completely oblivious about what to do with references, but
  1378 
  1390   properly treats ``data slots''!
  1379   Since storing theorems in a special list is such a common task, there is the
  1391 
       
  1392   Since storing theorems in a list is such a common task, there is the special
  1380   functor @{text NamedThmsFun}, which does most of the work for you. To obtain
  1393   functor @{text NamedThmsFun}, which does most of the work for you. To obtain
  1381   such a named theorem lists, you just declare
  1394   a named theorem lists, you just declare
  1382 *}
  1395 *}
  1383 
  1396 
  1384 ML{*structure FooRules = NamedThmsFun 
  1397 ML{*structure FooRules = NamedThmsFun 
  1385  (val name = "foo" 
  1398  (val name = "foo" 
  1386   val description = "Rules for foo") *}
  1399   val description = "Rules for foo") *}
  1431 
  1444 
  1432   (FIXME What are: @{text "theory_attributes"}, @{text "proof_attributes"}?)
  1445   (FIXME What are: @{text "theory_attributes"}, @{text "proof_attributes"}?)
  1433 
  1446 
  1434 
  1447 
  1435   \begin{readmore}
  1448   \begin{readmore}
  1436   FIXME: @{ML_file "Pure/more_thm.ML"} @{ML_file "Pure/Isar/attrib.ML"}
  1449   FIXME: @{ML_file "Pure/more_thm.ML"}; parsers for attributes is in 
       
  1450   @{ML_file "Pure/Isar/attrib.ML"}...also explained in the chapter about
       
  1451   parsing.
  1437   \end{readmore}
  1452   \end{readmore}
  1438 *}
  1453 *}
  1439 
  1454 
  1440 
  1455 
  1441 section {* Setups (TBD) *}
  1456 section {* Setups (TBD) *}