7 Functions for reading theory files, and storing and retrieving theories, |
7 Functions for reading theory files, and storing and retrieving theories, |
8 theorems and the global simplifier set. |
8 theorems and the global simplifier set. |
9 *) |
9 *) |
10 |
10 |
11 (*Type for theory storage*) |
11 (*Type for theory storage*) |
12 datatype thy_info = ThyInfo of {path: string, |
12 datatype thy_info = |
13 children: string list, |
13 ThyInfo of {path: string, |
14 thy_time: string option, |
14 children: string list, parents: string list, |
15 ml_time: string option, |
15 thy_time: string option, ml_time: string option, |
16 theory: theory option, |
16 theory: theory option, thms: thm Symtab.table, |
17 thms: thm Symtab.table, |
17 thy_ss: Simplifier.simpset option, |
18 thy_ss: Simplifier.simpset option, |
18 simpset: Simplifier.simpset option}; |
19 simpset: Simplifier.simpset option}; |
|
20 (*meaning of special values: |
19 (*meaning of special values: |
21 thy_time, ml_time = None theory file has not been read yet |
20 thy_time, ml_time = None theory file has not been read yet |
22 = Some "" theory was read but has either been marked |
21 = Some "" theory was read but has either been marked |
23 as outdated or there is no such file for |
22 as outdated or there is no such file for |
24 this theory (see e.g. 'virtual' theories |
23 this theory (see e.g. 'virtual' theories |
25 like Pure or theories without a ML file) |
24 like Pure or theories without a ML file) |
26 theory = None theory has not been read yet |
25 theory = None theory has not been read yet |
|
26 |
|
27 parents: While 'children' contains all theories the theory depends |
|
28 on (i.e. also ones quoted in the .thy file), |
|
29 'parents' only contains the theories which were used to form |
|
30 the base of this theory. |
|
31 |
|
32 origin of the simpsets: |
|
33 thy_ss: snapshot of !Simpset.simpset after .thy file was read |
|
34 simpset: snapshot of !Simpset.simpset after .ML file was read |
27 *) |
35 *) |
28 |
36 |
29 signature READTHY = |
37 signature READTHY = |
30 sig |
38 sig |
31 datatype basetype = Thy of string |
39 datatype basetype = Thy of string |
64 open ThmDB Simplifier; |
81 open ThmDB Simplifier; |
65 |
82 |
66 datatype basetype = Thy of string |
83 datatype basetype = Thy of string |
67 | File of string; |
84 | File of string; |
68 |
85 |
69 val loaded_thys = ref (Symtab.make [("ProtoPure", |
86 val loaded_thys = |
70 ThyInfo {path = "", |
87 ref (Symtab.make [("ProtoPure", |
71 children = ["Pure", "CPure"], |
88 ThyInfo {path = "", |
72 thy_time = Some "", ml_time = Some "", |
89 children = ["Pure", "CPure"], parents = [], |
73 theory = Some proto_pure_thy, |
90 thy_time = Some "", ml_time = Some "", |
74 thms = Symtab.null, |
91 theory = Some proto_pure_thy, thms = Symtab.null, |
75 thy_ss = None, simpset = None}), |
92 thy_ss = None, simpset = None}), |
76 ("Pure", ThyInfo {path = "", children = [], |
93 ("Pure", |
77 thy_time = Some "", ml_time = Some "", |
94 ThyInfo {path = "", children = [], |
78 theory = Some pure_thy, |
95 parents = ["ProtoPure"], |
79 thms = Symtab.null, |
96 thy_time = Some "", ml_time = Some "", |
80 thy_ss = None, simpset = None}), |
97 theory = Some pure_thy, thms = Symtab.null, |
81 ("CPure", ThyInfo {path = "", |
98 thy_ss = None, simpset = None}), |
82 children = [], |
99 ("CPure", |
83 thy_time = Some "", ml_time = Some "", |
100 ThyInfo {path = "", |
84 theory = Some cpure_thy, |
101 children = [], parents = ["ProtoPure"], |
85 thms = Symtab.null, |
102 thy_time = Some "", ml_time = Some "", |
86 thy_ss = None, simpset = None}) |
103 theory = Some cpure_thy, |
87 ]); |
104 thms = Symtab.null, |
88 |
105 thy_ss = None, simpset = None}) |
89 val loadpath = ref ["."]; (*default search path for theory files *) |
106 ]); |
90 |
107 |
91 val delete_tmpfiles = ref true; (*remove temporary files after use *) |
108 val loadpath = ref ["."]; (*default search path for theory files*) |
|
109 |
|
110 val delete_tmpfiles = ref true; (*remove temporary files after use*) |
|
111 |
|
112 |
|
113 (*Set location of graphics for HTML files |
|
114 (When this is executed for the first time we are in $ISABELLE/Pure/Thy. |
|
115 This path is converted to $ISABELLE/Tools by removing the last two |
|
116 directories and appending "Tools". All subsequently made ReadThy |
|
117 structures inherit this value.) |
|
118 *) |
|
119 val gif_path = ref (tack_on ("/" ^ |
|
120 space_implode "/" (rev (tl (tl (rev (space_explode "/" (pwd ()))))))) |
|
121 "Tools"); |
|
122 |
|
123 (*Location of theory-list.txt and 00-chart.html (normally set by init_html)*) |
|
124 val chart00_path = ref ""; |
|
125 |
|
126 val make_html = ref false; (*don't make HTML versions of loaded theories*) |
|
127 |
|
128 (*HTML file of theory currently being read |
|
129 (Initialized by thyfile2html; used by use_thy and store_thm)*) |
|
130 val cur_htmlfile = ref None : outstream option ref; |
|
131 |
92 |
132 |
93 (*Make name of the output ML file for a theory *) |
133 (*Make name of the output ML file for a theory *) |
94 fun out_name tname = "." ^ tname ^ ".thy.ML"; |
134 fun out_name tname = "." ^ tname ^ ".thy.ML"; |
95 |
135 |
96 (*Read a file specified by thy_file containing theory thy *) |
136 (*Read a file specified by thy_file containing theory thy *) |
134 else |
174 else |
135 (false, false) |
175 (false, false) |
136 end |
176 end |
137 | None => (false, false) |
177 | None => (false, false) |
138 |
178 |
|
179 (*Get all direct descendants of a theory*) |
|
180 fun children_of t = |
|
181 case get_thyinfo t of Some (ThyInfo {children, ...}) => children |
|
182 | _ => []; |
|
183 |
139 (*Get all direct ancestors of a theory*) |
184 (*Get all direct ancestors of a theory*) |
140 fun get_parents child = |
185 fun parents_of t = |
141 let fun has_child (tname, ThyInfo {children, theory, ...}) = |
186 case get_thyinfo t of Some (ThyInfo {parents, ...}) => parents |
142 if child mem children then Some tname else None; |
187 | _ => []; |
143 in mapfilter has_child (Symtab.dest (!loaded_thys)) end; |
|
144 |
188 |
145 (*Get all descendants of a theory list *) |
189 (*Get all descendants of a theory list *) |
146 fun get_descendants [] = [] |
190 fun get_descendants [] = [] |
147 | get_descendants (t :: ts) = |
191 | get_descendants (t :: ts) = |
148 let val tinfo = get_thyinfo t |
192 let val children = children_of t |
149 in if is_some tinfo then |
193 in children union (get_descendants (children union ts)) end; |
150 let val ThyInfo {children, ...} = the tinfo |
|
151 in children union (get_descendants (children union ts)) |
|
152 end |
|
153 else [] |
|
154 end; |
|
155 |
194 |
156 (*Get theory object for a loaded theory *) |
195 (*Get theory object for a loaded theory *) |
157 fun get_theory name = |
196 fun theory_of name = |
158 let val ThyInfo {theory, ...} = the (get_thyinfo name) |
197 let val ThyInfo {theory, ...} = the (get_thyinfo name) |
159 in the theory end; |
198 in the theory end; |
|
199 |
|
200 (*Get path where theory's files are located*) |
|
201 fun path_of tname = |
|
202 let val ThyInfo {path, ...} = the (get_thyinfo tname) |
|
203 in path end; |
160 |
204 |
161 exception FILE_NOT_FOUND; (*raised by find_file *) |
205 exception FILE_NOT_FOUND; (*raised by find_file *) |
162 |
206 |
163 (*Find a file using a list of paths if no absolute or relative path is |
207 (*Find a file using a list of paths if no absolute or relative path is |
164 specified.*) |
208 specified.*) |
165 fun find_file "" name = |
209 fun find_file "" name = |
166 let fun find_it (curr :: paths) = |
210 let fun find_it (cur :: paths) = |
167 if file_exists (tack_on curr name) then |
211 if file_exists (tack_on cur name) then |
168 tack_on curr name |
212 (if cur = "." then name else tack_on cur name) |
169 else |
213 else |
170 find_it paths |
214 find_it paths |
171 | find_it [] = "" |
215 | find_it [] = "" |
172 in find_it (!loadpath) end |
216 in find_it (!loadpath) end |
173 | find_file path name = |
217 | find_file path name = |
174 if file_exists (tack_on path name) then tack_on path name |
218 if file_exists (tack_on path name) then tack_on path name |
175 else ""; |
219 else ""; |
232 (Symtab.dest (!loaded_thys))); |
276 (Symtab.dest (!loaded_thys))); |
233 |
277 |
234 (*Change thy_time and ml_time for an existent item *) |
278 (*Change thy_time and ml_time for an existent item *) |
235 fun set_info tname thy_time ml_time = |
279 fun set_info tname thy_time ml_time = |
236 let val tinfo = case Symtab.lookup (!loaded_thys, tname) of |
280 let val tinfo = case Symtab.lookup (!loaded_thys, tname) of |
237 Some (ThyInfo {path, children, theory, thms, thy_ss, simpset,...}) => |
281 Some (ThyInfo {path, children, parents, theory, thms, |
238 ThyInfo {path = path, children = children, |
282 thy_ss, simpset,...}) => |
|
283 ThyInfo {path = path, children = children, parents = parents, |
239 thy_time = thy_time, ml_time = ml_time, |
284 thy_time = thy_time, ml_time = ml_time, |
240 theory = theory, thms = thms, |
285 theory = theory, thms = thms, |
241 thy_ss = thy_ss, simpset = simpset} |
286 thy_ss = thy_ss, simpset = simpset} |
242 | None => ThyInfo {path = "", children = [], |
287 | None => error ("set_info: theory " ^ tname ^ " not found"); |
243 thy_time = thy_time, ml_time = ml_time, |
|
244 theory = None, thms = Symtab.null, |
|
245 thy_ss = None, simpset = None}; |
|
246 in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys) |
288 in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys) |
247 end; |
289 end; |
248 |
290 |
249 (*Mark theory as changed since last read if it has been completly read *) |
291 (*Mark theory as changed since last read if it has been completly read *) |
250 fun mark_outdated tname = |
292 fun mark_outdated tname = |
251 let val t = get_thyinfo tname; |
293 let val t = get_thyinfo tname; |
252 in if is_none t then () |
294 in if is_none t then () |
253 else let val ThyInfo {thy_time, ml_time, ...} = the t |
295 else |
254 in set_info tname |
296 let val ThyInfo {thy_time, ml_time, ...} = the t |
255 (if is_none thy_time then None else Some "") |
297 in set_info tname (if is_none thy_time then None else Some "") |
256 (if is_none ml_time then None else Some "") |
298 (if is_none ml_time then None else Some "") |
257 |
299 end |
258 end |
300 end; |
259 end; |
301 |
|
302 (*Make head of HTML dependency charts |
|
303 Parameters are: |
|
304 file: HTML file |
|
305 tname: theory name |
|
306 suffix: suffix of complementary chart |
|
307 (sup if this head is for a sub-chart, sub if it is for a sup-chart; |
|
308 empty for Pure and CPure sub-charts) |
|
309 gif_path: relative path to directory containing GIFs |
|
310 chart00_path: relative path to directory containing main theory chart |
|
311 *) |
|
312 fun mk_charthead file tname title green_arrow gif_path chart00_path package = |
|
313 output (file, |
|
314 "<HTML><HEAD><TITLE>" ^ title ^ " of " ^ tname ^ |
|
315 "</TITLE></HEAD>\n<H2>" ^ title ^ " of theory " ^ tname ^ |
|
316 "</H2>\nThe name of every theory is linked to its theory file<BR>\n" ^ |
|
317 "<IMG SRC = \"" ^ tack_on gif_path "red_arrow.gif\ |
|
318 \\" ALT = \\/></A> stands for subtheories (child theories)<BR>\n\ |
|
319 \<IMG SRC = \"" ^ tack_on gif_path "blue_arrow.gif\ |
|
320 \\" ALT = /\\></A> stands for supertheories (parent theories)\n" ^ |
|
321 (if not green_arrow then "" else |
|
322 "<BR><IMG SRC = \"" ^ tack_on gif_path "green_arrow.gif\ |
|
323 \\" ALT = >></A> stands for repeated subtrees") ^ |
|
324 "<P><A HREF = \"" ^ tack_on chart00_path "00-chart.html\ |
|
325 \\">Back</A> to the main theory chart of " ^ package ^ ".\n<HR>\n<PRE>"); |
|
326 |
|
327 (*Convert .thy file to HTML and make chart of its super-theories*) |
|
328 fun thyfile2html tpath tname = |
|
329 let |
|
330 val gif_path = relative_path tpath (!gif_path); |
|
331 val package = hd (rev (space_explode "/" (!chart00_path))); |
|
332 val chart00_path = relative_path tpath (!chart00_path); |
|
333 |
|
334 (*Make list of all theories and all theories that own a .thy file*) |
|
335 fun list_theories [] theories thy_files = (theories, thy_files) |
|
336 | list_theories ((tname, ThyInfo {thy_time, ...}) :: ts) |
|
337 theories thy_files = |
|
338 list_theories ts (tname :: theories) |
|
339 (if is_some thy_time andalso the thy_time <> "" then |
|
340 tname :: thy_files |
|
341 else thy_files); |
|
342 |
|
343 val (theories, thy_files) = |
|
344 list_theories (Symtab.dest (!loaded_thys)) [] []; |
|
345 |
|
346 (*Do the conversion*) |
|
347 fun gettext thy_file = |
|
348 let |
|
349 (*Convert special HTML characters ('&', '>', and '<')*) |
|
350 val file = |
|
351 explode (execute ("sed -e 's/\\&/\\&/g' -e 's/>/\\>/g' \ |
|
352 \-e 's/</\\</g' " ^ thy_file)); |
|
353 |
|
354 (*Isolate first (possibly nested) comment; |
|
355 skip all leading whitespaces*) |
|
356 val (comment, file') = |
|
357 let fun first_comment ("*" :: ")" :: cs) co 1 = (co ^ "*)", cs) |
|
358 | first_comment ("*" :: ")" :: cs) co d = |
|
359 first_comment cs (co ^ "*)") (d-1) |
|
360 | first_comment ("(" :: "*" :: cs) co d = |
|
361 first_comment cs (co ^ "(*") (d+1) |
|
362 | first_comment (" " :: cs) "" 0 = first_comment cs "" 0 |
|
363 | first_comment ("\n" :: cs) "" 0 = first_comment cs "" 0 |
|
364 | first_comment ("\t" :: cs) "" 0 = first_comment cs "" 0 |
|
365 | first_comment cs "" 0 = ("", cs) |
|
366 | first_comment (c :: cs) co d = |
|
367 first_comment cs (co ^ implode [c]) d |
|
368 | first_comment [] co _ = |
|
369 error ("Unexpected end of file " ^ tname ^ ".thy."); |
|
370 in first_comment file "" 0 end; |
|
371 |
|
372 (*Process line defining theory's ancestors; |
|
373 convert valid theory names to links to their HTML file*) |
|
374 val (ancestors, body) = |
|
375 let |
|
376 fun make_links l result = |
|
377 let val (pre, letter) = take_prefix (not o is_letter) l; |
|
378 |
|
379 val (id, rest) = |
|
380 take_prefix (is_quasi_letter orf is_digit) letter; |
|
381 |
|
382 val id = implode id; |
|
383 |
|
384 (*Make a HTML link out of a theory name*) |
|
385 fun make_link t = |
|
386 let val path = path_of t; |
|
387 in "<A HREF = \"" ^ |
|
388 tack_on (relative_path tpath path) t ^ |
|
389 ".html\">" ^ t ^ "</A>" end; |
|
390 in if not (id mem theories) then (result, implode l) |
|
391 else if id mem thy_files then |
|
392 make_links rest (result ^ implode pre ^ make_link id) |
|
393 else make_links rest (result ^ implode pre ^ id) |
|
394 end; |
|
395 |
|
396 val (pre, rest) = take_prefix (fn c => c <> "=") file'; |
|
397 |
|
398 val (ancestors, body) = |
|
399 if null rest then |
|
400 error ("Missing \"=\" in file " ^ tname ^ ".thy.\n\ |
|
401 \(Make sure that the last line ends with a linebreak.)") |
|
402 else |
|
403 make_links rest ""; |
|
404 in (implode pre ^ ancestors, body) end; |
|
405 in "<HTML><HEAD><TITLE>" ^ tname ^ ".thy</TITLE></HEAD>\n\n<BODY>\n" ^ |
|
406 "<H2>" ^ tname ^ ".thy</H2>\n<A HREF = \"" ^ |
|
407 tack_on chart00_path "00-chart.html\ |
|
408 \\">Back</A> to the main theory chart of " ^ package ^ |
|
409 ".\n<HR>\n\n<PRE>\n" ^ comment ^ ancestors ^ body ^ |
|
410 "</PRE>\n<HR><H2>Theorems proved in <A HREF = \"" ^ tname ^ |
|
411 ".ML\">" ^ tname ^ ".ML</A>:</H2>\n" |
|
412 end; |
|
413 |
|
414 (** Make chart of super-theories **) |
|
415 |
|
416 val sup_out = open_out (tack_on tpath tname ^ "_sup.html"); |
|
417 val sub_out = open_out (tack_on tpath tname ^ "_sub.html"); |
|
418 |
|
419 (*Theories that already have been listed in this chart*) |
|
420 val listed = ref []; |
|
421 |
|
422 val wanted_theories = |
|
423 filter (fn s => s mem thy_files orelse s = "Pure" orelse s = "CPure") |
|
424 theories; |
|
425 |
|
426 (*Make nested list of theories*) |
|
427 fun list_ancestors tname level continued = |
|
428 let |
|
429 fun mk_entry [] = () |
|
430 | mk_entry (t::ts) = |
|
431 let |
|
432 val is_pure = t = "Pure" orelse t = "CPure"; |
|
433 val path = path_of t; |
|
434 val rel_path = if is_pure then chart00_path |
|
435 else relative_path tpath path; |
|
436 |
|
437 fun mk_offset [] cur = |
|
438 if level < cur then error "Error in mk_offset" |
|
439 else implode (replicate (level - cur) " ") |
|
440 | mk_offset (l::ls) cur = |
|
441 implode (replicate (l - cur) " ") ^ "| " ^ |
|
442 mk_offset ls (l+1); |
|
443 in output (sup_out, |
|
444 " " ^ mk_offset continued 0 ^ |
|
445 "\\__" ^ (if is_pure then t else "<A HREF=\"" ^ |
|
446 tack_on rel_path t ^ ".html\">" ^ t ^ "</A>") ^ |
|
447 " <A HREF = \"" ^ tack_on rel_path t ^ |
|
448 "_sub.html\"><IMG ALIGN=TOP SRC = \"" ^ |
|
449 tack_on gif_path "red_arrow.gif\" ALT = \\/></A>" ^ |
|
450 (if is_pure then "" |
|
451 else "<A HREF = \"" ^ tack_on rel_path t ^ |
|
452 "_sup.html\"><IMG ALIGN=TOP SRC = \"" ^ |
|
453 tack_on gif_path "blue_arrow.gif\ |
|
454 \\" ALT = /\\></A>")); |
|
455 if t mem (!listed) andalso not (null (parents_of t)) then |
|
456 output (sup_out, |
|
457 "<A HREF = \"" ^ tack_on rel_path t ^ "_sup.html\">\ |
|
458 \<IMG ALIGN=TOP SRC = \"" ^ |
|
459 tack_on gif_path "green_arrow.gif\" ALT = >></A>\n") |
|
460 else (output (sup_out, "\n"); |
|
461 listed := t :: (!listed); |
|
462 list_ancestors t (level+1) (if null ts then continued |
|
463 else continued @ [level]); |
|
464 mk_entry ts) |
|
465 end; |
|
466 |
|
467 val relatives = |
|
468 filter (fn s => s mem wanted_theories) (parents_of tname); |
|
469 in mk_entry relatives end; |
|
470 in if is_some (!cur_htmlfile) then |
|
471 error "thyfile2html: Last theory's HTML has not been closed." |
|
472 else (); |
|
473 cur_htmlfile := Some (open_out (tack_on tpath tname ^ ".html")); |
|
474 output (the (!cur_htmlfile), gettext (tack_on tpath tname ^ ".thy")); |
|
475 |
|
476 mk_charthead sup_out tname "Ancestors" true gif_path chart00_path package; |
|
477 output(sup_out, |
|
478 "<A HREF=\"" ^ tname ^ ".html\">" ^ tname ^ "</A> \ |
|
479 \<A HREF = \"" ^ tname ^ "_sub.html\"><IMG ALIGN=TOP SRC = \"" ^ |
|
480 tack_on gif_path "red_arrow.gif\" ALT = \\/></A>\n"); |
|
481 list_ancestors tname 0 []; |
|
482 output (sup_out, "</PRE><HR></BODY></HTML>"); |
|
483 close_out sup_out; |
|
484 |
|
485 mk_charthead sub_out tname "Children" false gif_path chart00_path package; |
|
486 output(sub_out, |
|
487 "<A HREF=\"" ^ tname ^ ".html\">" ^ tname ^ "</A> \ |
|
488 \<A HREF = \"" ^ tname ^ "_sup.html\"><IMG SRC = \"" ^ |
|
489 tack_on gif_path "blue_arrow.gif\" ALT = \\/></A>\n"); |
|
490 close_out sub_out |
|
491 end; |
|
492 |
260 |
493 |
261 (*Read .thy and .ML files that haven't been read yet or have changed since |
494 (*Read .thy and .ML files that haven't been read yet or have changed since |
262 they were last read; |
495 they were last read; |
263 loaded_thys is a thy_info list ref containing all theories that have |
496 loaded_thys is a thy_info list ref containing all theories that have |
264 completly been read by this and preceeding use_thy calls. |
497 completly been read by this and preceeding use_thy calls. |
268 val (path, tname) = split_filename name; |
501 val (path, tname) = split_filename name; |
269 val (thy_file, ml_file) = get_filenames path tname; |
502 val (thy_file, ml_file) = get_filenames path tname; |
270 val (abs_path, _) = if thy_file = "" then split_filename ml_file |
503 val (abs_path, _) = if thy_file = "" then split_filename ml_file |
271 else split_filename thy_file; |
504 else split_filename thy_file; |
272 val (thy_uptodate, ml_uptodate) = thy_unchanged tname thy_file ml_file; |
505 val (thy_uptodate, ml_uptodate) = thy_unchanged tname thy_file ml_file; |
|
506 val old_parents = parents_of tname; |
273 |
507 |
274 (*Set absolute path for loaded theory *) |
508 (*Set absolute path for loaded theory *) |
275 fun set_path () = |
509 fun set_path () = |
276 let val ThyInfo {children, thy_time, ml_time, theory, thms, thy_ss, |
510 let val ThyInfo {children, parents, thy_time, ml_time, theory, thms, |
277 simpset, ...} = |
511 thy_ss, simpset, ...} = |
278 the (Symtab.lookup (!loaded_thys, tname)); |
512 the (Symtab.lookup (!loaded_thys, tname)); |
279 in loaded_thys := Symtab.update ((tname, |
513 in loaded_thys := Symtab.update ((tname, |
280 ThyInfo {path = abs_path, children = children, |
514 ThyInfo {path = abs_path, |
|
515 children = children, parents = parents, |
281 thy_time = thy_time, ml_time = ml_time, |
516 thy_time = thy_time, ml_time = ml_time, |
282 theory = theory, thms = thms, |
517 theory = theory, thms = thms, |
283 thy_ss = thy_ss, simpset = simpset}), |
518 thy_ss = thy_ss, simpset = simpset}), |
284 !loaded_thys) |
519 !loaded_thys) |
285 end; |
520 end; |
286 |
521 |
287 (*Mark all direct descendants of a theory as changed *) |
522 (*Mark all direct descendants of a theory as changed *) |
288 fun mark_children thy = |
523 fun mark_children thy = |
289 let val ThyInfo {children, ...} = the (get_thyinfo thy); |
524 let val children = children_of thy; |
290 val present = filter (is_some o get_thyinfo) children; |
525 val present = filter (is_some o get_thyinfo) children; |
291 val loaded = filter already_loaded present; |
526 val loaded = filter already_loaded present; |
292 in if loaded <> [] then |
527 in if loaded <> [] then |
293 writeln ("The following children of theory " ^ (quote thy) |
528 writeln ("The following children of theory " ^ (quote thy) |
294 ^ " are now out-of-date: " |
529 ^ " are now out-of-date: " |
299 |
534 |
300 (*Remove theorems associated with a theory*) |
535 (*Remove theorems associated with a theory*) |
301 fun delete_thms () = |
536 fun delete_thms () = |
302 let |
537 let |
303 val tinfo = case get_thyinfo tname of |
538 val tinfo = case get_thyinfo tname of |
304 Some (ThyInfo {path, children, thy_time, ml_time, theory, thy_ss, |
539 Some (ThyInfo {path, children, parents, thy_time, ml_time, theory, |
305 simpset, ...}) => |
540 thy_ss, simpset, ...}) => |
306 ThyInfo {path = path, children = children, |
541 ThyInfo {path = path, children = children, parents = parents, |
307 thy_time = thy_time, ml_time = ml_time, |
542 thy_time = thy_time, ml_time = ml_time, |
308 theory = theory, thms = Symtab.null, |
543 theory = theory, thms = Symtab.null, |
309 thy_ss = thy_ss, simpset = simpset} |
544 thy_ss = thy_ss, simpset = simpset} |
310 | None => ThyInfo {path = "", children = [], |
545 | None => ThyInfo {path = "", children = [], parents = [], |
311 thy_time = None, ml_time = None, |
546 thy_time = None, ml_time = None, |
312 theory = None, thms = Symtab.null, |
547 theory = None, thms = Symtab.null, |
313 thy_ss = None, simpset = None}; |
548 thy_ss = None, simpset = None}; |
314 |
549 |
315 val ThyInfo {theory, ...} = tinfo; |
550 val ThyInfo {theory, ...} = tinfo; |
318 Some t => delete_thm_db t |
553 Some t => delete_thm_db t |
319 | None => () |
554 | None => () |
320 end; |
555 end; |
321 |
556 |
322 fun save_thy_ss () = |
557 fun save_thy_ss () = |
323 let val ThyInfo {path, children, thy_time, ml_time, theory, thms, |
558 let val ThyInfo {path, children, parents, thy_time, ml_time, |
324 simpset, ...} = the (get_thyinfo tname); |
559 theory, thms, simpset, ...} = the (get_thyinfo tname); |
325 in loaded_thys := Symtab.update |
560 in loaded_thys := Symtab.update |
326 ((tname, ThyInfo {path = path, children = children, |
561 ((tname, ThyInfo {path = path, |
|
562 children = children, parents = parents, |
327 thy_time = thy_time, ml_time = ml_time, |
563 thy_time = thy_time, ml_time = ml_time, |
328 theory = theory, thms = thms, |
564 theory = theory, thms = thms, |
329 thy_ss = Some (!Simplifier.simpset), |
565 thy_ss = Some (!Simplifier.simpset), |
330 simpset = simpset}), |
566 simpset = simpset}), |
331 !loaded_thys) |
567 !loaded_thys) |
332 end; |
568 end; |
333 |
569 |
334 fun save_simpset () = |
570 fun save_simpset () = |
335 let val ThyInfo {path, children, thy_time, ml_time, theory, thms, |
571 let val ThyInfo {path, children, parents, thy_time, ml_time, |
336 thy_ss, ...} = the (get_thyinfo tname); |
572 theory, thms, thy_ss, ...} = the (get_thyinfo tname); |
337 in loaded_thys := Symtab.update |
573 in loaded_thys := Symtab.update |
338 ((tname, ThyInfo {path = path, children = children, |
574 ((tname, ThyInfo {path = path, |
|
575 children = children, parents = parents, |
339 thy_time = thy_time, ml_time = ml_time, |
576 thy_time = thy_time, ml_time = ml_time, |
340 theory = theory, thms = thms, |
577 theory = theory, thms = thms, |
341 thy_ss = thy_ss, |
578 thy_ss = thy_ss, |
342 simpset = Some (!Simplifier.simpset)}), |
579 simpset = Some (!Simplifier.simpset)}), |
343 !loaded_thys) |
580 !loaded_thys) |
344 end; |
581 end; |
345 |
582 |
|
583 (*Add theory to file listing all loaded theories (for 00-chart.html) |
|
584 and to the sub-charts of its parents*) |
|
585 fun mk_html () = |
|
586 let val new_parents = parents_of tname \\ old_parents; |
|
587 |
|
588 (*Add child to parents' sub-theory charts*) |
|
589 fun add_to_parents t = |
|
590 let val is_pure = t = "Pure" orelse t = "CPure"; |
|
591 val path = if is_pure then (!chart00_path) else path_of t; |
|
592 |
|
593 val gif_path = relative_path path (!gif_path); |
|
594 val rel_path = relative_path path abs_path; |
|
595 |
|
596 val out = open_append (tack_on path t ^ "_sub.html"); |
|
597 in output (out, |
|
598 " |\n \\__<A HREF=\"" ^ tack_on rel_path tname ^ ".html\">" ^ |
|
599 tname ^ "</A> <A HREF = \"" ^ |
|
600 tack_on rel_path tname ^ |
|
601 "_sub.html\"><IMG ALIGN=TOP SRC = \"" ^ |
|
602 tack_on gif_path "red_arrow.gif\" ALT = \\/></A>\ |
|
603 \<A HREF = \"" ^ tack_on rel_path tname ^ "_sup.html\">\ |
|
604 \<IMG ALIGN=TOP SRC = \"" ^ tack_on gif_path "blue_arrow.gif\ |
|
605 \\" ALT = /\\></A>\n"); |
|
606 close_out out |
|
607 end; |
|
608 |
|
609 val theory_list = |
|
610 open_append (tack_on (!chart00_path) "theory_list.txt"); |
|
611 in output (theory_list, tname ^ " " ^ abs_path ^ "\n"); |
|
612 close_out theory_list; |
|
613 |
|
614 seq add_to_parents new_parents |
|
615 end |
346 in if thy_uptodate andalso ml_uptodate then () |
616 in if thy_uptodate andalso ml_uptodate then () |
347 else |
617 else |
348 ( |
618 (if thy_file = "" then () |
349 if thy_file = "" then () |
|
350 else if thy_uptodate then |
619 else if thy_uptodate then |
351 simpset := let val ThyInfo {thy_ss, ...} = the (get_thyinfo tname); |
620 simpset := let val ThyInfo {thy_ss, ...} = the (get_thyinfo tname); |
352 in the thy_ss end |
621 in the thy_ss end |
353 else |
622 else |
354 (writeln ("Reading \"" ^ name ^ ".thy\""); |
623 (writeln ("Reading \"" ^ name ^ ".thy\""); |
|
624 |
355 delete_thms (); |
625 delete_thms (); |
356 read_thy tname thy_file; |
626 read_thy tname thy_file; |
357 use (out_name tname); |
627 use (out_name tname); |
358 save_thy_ss (); |
628 save_thy_ss (); |
359 |
629 |
360 if not (!delete_tmpfiles) then () |
630 if not (!delete_tmpfiles) then () |
361 else delete_file (out_name tname) |
631 else delete_file (out_name tname); |
|
632 |
|
633 if not (!make_html) then () |
|
634 else thyfile2html abs_path tname |
362 ); |
635 ); |
363 |
636 |
364 set_info tname (Some (file_info thy_file)) None; |
637 set_info tname (Some (file_info thy_file)) None; |
365 (*mark thy_file as successfully loaded*) |
638 (*mark thy_file as successfully loaded*) |
366 |
639 |
466 end |
749 end |
467 else () |
750 else () |
468 end |
751 end |
469 in find_it "" child end; |
752 in find_it "" child end; |
470 |
753 |
471 (*Check if a cycle would be created by add_child *) |
754 (*Check if a cycle would be created by add_child*) |
472 fun find_cycle base = |
755 fun find_cycle base = |
473 if base mem (get_descendants [child]) then show_cycle base |
756 if base mem (get_descendants [child]) then show_cycle base |
474 else (); |
757 else (); |
475 |
758 |
476 (*Add child to child list of base *) |
759 (*Add child to child list of base*) |
477 fun add_child base = |
760 fun add_child base = |
478 let val tinfo = |
761 let val tinfo = |
479 case Symtab.lookup (!loaded_thys, base) of |
762 case Symtab.lookup (!loaded_thys, base) of |
480 Some (ThyInfo {path, children, thy_time, ml_time, |
763 Some (ThyInfo {path, children, parents, thy_time, ml_time, |
481 theory, thms, thy_ss, simpset}) => |
764 theory, thms, thy_ss, simpset}) => |
482 ThyInfo {path = path, children = child ins children, |
765 ThyInfo {path = path, |
|
766 children = child ins children, parents = parents, |
483 thy_time = thy_time, ml_time = ml_time, |
767 thy_time = thy_time, ml_time = ml_time, |
484 theory = theory, thms = thms, |
768 theory = theory, thms = thms, |
485 thy_ss = thy_ss, simpset = simpset} |
769 thy_ss = thy_ss, simpset = simpset} |
486 | None => ThyInfo {path = "", children = [child], |
770 | None => ThyInfo {path = "", children = [child], parents = [], |
487 thy_time = None, ml_time = None, |
771 thy_time = None, ml_time = None, |
488 theory = None, thms = Symtab.null, |
772 theory = None, thms = Symtab.null, |
489 thy_ss = None, simpset = None}; |
773 thy_ss = None, simpset = None}; |
490 in loaded_thys := Symtab.update ((base, tinfo), !loaded_thys) end; |
774 in loaded_thys := Symtab.update ((base, tinfo), !loaded_thys) end; |
491 |
775 |
514 in simpset end; |
798 in simpset end; |
515 |
799 |
516 (*Load all needed files and make a list of all real theories *) |
800 (*Load all needed files and make a list of all real theories *) |
517 fun load_base (Thy b :: bs) = |
801 fun load_base (Thy b :: bs) = |
518 (load b; |
802 (load b; |
519 b :: (load_base bs)) |
803 b :: load_base bs) |
520 | load_base (File b :: bs) = |
804 | load_base (File b :: bs) = |
521 (load b; |
805 (load b; |
522 load_base bs) (*don't add it to mergelist *) |
806 load_base bs) (*don't add it to mergelist *) |
523 | load_base [] = []; |
807 | load_base [] = []; |
524 |
808 |
525 val dummy = unlink_thy child; |
809 val dummy = unlink_thy child; |
526 val mergelist = load_base bases; |
810 val mergelist = load_base bases; |
527 |
811 |
|
812 val dummy = |
|
813 let val tinfo = case Symtab.lookup (!loaded_thys, child) of |
|
814 Some (ThyInfo {path, children, thy_time, ml_time, theory, thms, |
|
815 thy_ss, simpset, ...}) => |
|
816 ThyInfo {path = path, |
|
817 children = children, parents = mergelist, |
|
818 thy_time = thy_time, ml_time = ml_time, |
|
819 theory = theory, thms = thms, |
|
820 thy_ss = thy_ss, simpset = simpset} |
|
821 | None => error ("set_parents: theory " ^ child ^ " not found"); |
|
822 in loaded_thys := Symtab.update ((child, tinfo), !loaded_thys) end; |
|
823 |
528 val base_thy = (writeln ("Loading theory " ^ (quote child)); |
824 val base_thy = (writeln ("Loading theory " ^ (quote child)); |
529 merge_thy_list mk_draft (map get_theory mergelist)); |
825 merge_thy_list mk_draft (map theory_of mergelist)); |
530 in simpset := foldr merge_ss (mapfilter get_simpset mergelist, empty_ss); |
826 in simpset := foldr merge_ss (mapfilter get_simpset mergelist, empty_ss); |
531 base_thy |
827 base_thy |
532 end; |
828 end; |
533 |
829 |
534 (*Change theory object for an existent item of loaded_thys |
830 (*Change theory object for an existent item of loaded_thys*) |
535 or create a new item*) |
|
536 fun store_theory (thy, tname) = |
831 fun store_theory (thy, tname) = |
537 let val tinfo = case Symtab.lookup (!loaded_thys, tname) of |
832 let val tinfo = case Symtab.lookup (!loaded_thys, tname) of |
538 Some (ThyInfo {path, children, thy_time, ml_time, thms, |
833 Some (ThyInfo {path, children, parents, thy_time, ml_time, thms, |
539 thy_ss, simpset, ...}) => |
834 thy_ss, simpset, ...}) => |
540 ThyInfo {path = path, children = children, |
835 ThyInfo {path = path, children = children, parents = parents, |
541 thy_time = thy_time, ml_time = ml_time, |
836 thy_time = thy_time, ml_time = ml_time, |
542 theory = Some thy, thms = thms, |
837 theory = Some thy, thms = thms, |
543 thy_ss = thy_ss, simpset = simpset} |
838 thy_ss = thy_ss, simpset = simpset} |
544 | None => ThyInfo {path = "", children = [], |
839 | None => error ("store_theory: theory " ^ tname ^ " not found"); |
545 thy_time = None, ml_time = None, |
|
546 theory = Some thy, thms = Symtab.null, |
|
547 thy_ss = None, simpset = None}; |
|
548 in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys) |
840 in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys) |
549 end; |
841 end; |
550 |
842 |
551 |
843 |
552 (** store and retrieve theorems **) |
844 (** store and retrieve theorems **) |
581 val theory_of_thm = theory_of_sign o #sign o rep_thm; |
873 val theory_of_thm = theory_of_sign o #sign o rep_thm; |
582 |
874 |
583 |
875 |
584 (* Store theorems *) |
876 (* Store theorems *) |
585 |
877 |
586 (*Store a theorem in the thy_info of its theory*) |
878 (*Store a theorem in the thy_info of its theory, |
|
879 and in the theory's HTML file*) |
587 fun store_thm (name, thm) = |
880 fun store_thm (name, thm) = |
588 let |
881 let |
589 val (thy_name, ThyInfo {path, children, thy_time, ml_time, theory, thms, |
882 val (thy_name, ThyInfo {path, children, parents, thy_time, ml_time, |
590 thy_ss, simpset}) = |
883 theory, thms, thy_ss, simpset}) = |
591 thyinfo_of_sign (#sign (rep_thm thm)); |
884 thyinfo_of_sign (#sign (rep_thm thm)); |
592 |
885 |
593 val (thms', duplicate) = (Symtab.update_new ((name, thm), thms), false) |
886 val (thms', duplicate) = (Symtab.update_new ((name, thm), thms), false) |
594 handle Symtab.DUPLICATE s => |
887 handle Symtab.DUPLICATE s => |
595 (if eq_thm (the (Symtab.lookup (thms, name)), thm) then |
888 (if eq_thm (the (Symtab.lookup (thms, name)), thm) then |
596 (writeln ("Warning: Theory database already contains copy of\ |
889 (writeln ("Warning: Theory database already contains copy of\ |
597 \ theorem " ^ quote name); |
890 \ theorem " ^ quote name); |
598 (thms, true)) |
891 (thms, true)) |
599 else error ("Duplicate theorem name " ^ quote s |
892 else error ("Duplicate theorem name " ^ quote s |
600 ^ " used in theory database")); |
893 ^ " used in theory database")); |
|
894 |
|
895 fun thm_to_html () = |
|
896 let fun escape [] = "" |
|
897 | escape ("<"::s) = "<" ^ escape s |
|
898 | escape (">"::s) = ">" ^ escape s |
|
899 | escape ("&"::s) = "&" ^ escape s |
|
900 | escape (c::s) = c ^ escape s; |
|
901 in case !cur_htmlfile of |
|
902 Some out => |
|
903 output (out, "<EM>" ^ name ^ "</EM>\n<PRE>" ^ |
|
904 escape (explode (string_of_thm (freeze thm))) ^ |
|
905 "</PRE><P>\n") |
|
906 | None => () |
|
907 end; |
601 in |
908 in |
602 loaded_thys := Symtab.update |
909 loaded_thys := Symtab.update |
603 ((thy_name, ThyInfo {path = path, children = children, |
910 ((thy_name, ThyInfo {path = path, children = children, parents = parents, |
604 thy_time = thy_time, ml_time = ml_time, |
911 thy_time = thy_time, ml_time = ml_time, |
605 theory = theory, thms = thms', |
912 theory = theory, thms = thms', |
606 thy_ss = thy_ss, simpset = simpset}), |
913 thy_ss = thy_ss, simpset = simpset}), |
607 !loaded_thys); |
914 !loaded_thys); |
|
915 thm_to_html (); |
608 if duplicate then thm else store_thm_db (name, thm) |
916 if duplicate then thm else store_thm_db (name, thm) |
609 end; |
917 end; |
610 |
918 |
611 (*Store result of proof in loaded_thys and as ML value*) |
919 (*Store result of proof in loaded_thys and as ML value*) |
612 |
920 |
613 val qed_thm = ref flexpair_def(*dummy*); |
921 val qed_thm = ref flexpair_def(*dummy*); |
614 |
922 |
615 fun bind_thm (name, thm) = |
923 fun bind_thm (name, thm) = |
616 (qed_thm := standard thm; |
924 (qed_thm := standard thm; |
617 use_string ["val " ^name^ " = store_thm (" ^quote name^", !qed_thm);"]); |
925 store_thm (name, standard thm); |
|
926 use_string ["val " ^ name ^ " = !qed_thm;"]); |
618 |
927 |
619 fun qed name = |
928 fun qed name = |
620 use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^ ", result ());"]; |
929 (qed_thm := result (); |
|
930 store_thm (name, !qed_thm); |
|
931 use_string ["val " ^ name ^ " = !qed_thm;"]); |
621 |
932 |
622 fun qed_goal name thy agoal tacsf = |
933 fun qed_goal name thy agoal tacsf = |
623 (qed_thm := prove_goal thy agoal tacsf; |
934 (qed_thm := prove_goal thy agoal tacsf; |
624 use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^", !qed_thm);"]); |
935 store_thm (name, !qed_thm); |
|
936 use_string ["val " ^ name ^ " = !qed_thm;"]); |
625 |
937 |
626 fun qed_goalw name thy rths agoal tacsf = |
938 fun qed_goalw name thy rths agoal tacsf = |
627 (qed_thm := prove_goalw thy rths agoal tacsf; |
939 (qed_thm := prove_goalw thy rths agoal tacsf; |
628 use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^", !qed_thm);"]); |
940 store_thm (name, !qed_thm); |
|
941 use_string ["val " ^ name ^ " = !qed_thm;"]); |
629 |
942 |
630 |
943 |
631 (* Retrieve theorems *) |
944 (* Retrieve theorems *) |
632 |
945 |
633 (*Get all theorems belonging to a given theory*) |
946 (*Get all theorems belonging to a given theory*) |
675 Pretty.writeln (Pretty.big_list "stored theorems:" (map prt_thm thms)) |
988 Pretty.writeln (Pretty.big_list "stored theorems:" (map prt_thm thms)) |
676 end; |
989 end; |
677 |
990 |
678 fun print_theory thy = (Drule.print_theory thy; print_thms thy); |
991 fun print_theory thy = (Drule.print_theory thy; print_thms thy); |
679 |
992 |
|
993 |
|
994 (* Misc HTML functions *) |
|
995 |
|
996 (*Init HTML generator by setting paths and creating new files*) |
|
997 fun init_html () = |
|
998 let val pure_out = open_out "Pure_sub.html"; |
|
999 val cpure_out = open_out "CPure_sub.html"; |
|
1000 val theory_list = close_out (open_out "theory_list.txt"); |
|
1001 |
|
1002 val rel_gif_path = relative_path (pwd ()) (!gif_path); |
|
1003 val package = hd (rev (space_explode "/" (pwd ()))); |
|
1004 in make_html := true; |
|
1005 chart00_path := pwd(); |
|
1006 writeln ("Setting path for 00-chart.html to " ^ quote (!chart00_path) ^ |
|
1007 "\nGIF path has been set to " ^ quote (!gif_path)); |
|
1008 |
|
1009 mk_charthead pure_out "Pure" "Children" false rel_gif_path "" package; |
|
1010 mk_charthead cpure_out "CPure" "Children" false rel_gif_path "" package; |
|
1011 output (pure_out, "Pure\n"); |
|
1012 output (cpure_out, "CPure\n"); |
|
1013 close_out pure_out; |
|
1014 close_out cpure_out |
|
1015 end; |
|
1016 |
|
1017 (*Generate 00-chart.html*) |
|
1018 fun make_chart () = if not (!make_html) then () else |
|
1019 let val theory_list = open_in (tack_on (!chart00_path) "theory_list.txt"); |
|
1020 val theories = space_explode "\n" (input (theory_list, 999999)); |
|
1021 val dummy = close_in theory_list; |
|
1022 |
|
1023 (*Path to Isabelle's main directory = $gif_path/.. *) |
|
1024 val base_path = "/" ^ |
|
1025 space_implode "/" (rev (tl (rev (space_explode "/" (!gif_path))))); |
|
1026 |
|
1027 val gif_path = relative_path (!chart00_path) (!gif_path); |
|
1028 |
|
1029 (*Make entry for main chart of all theories.*) |
|
1030 fun main_entries [] curdir = |
|
1031 implode (replicate (length curdir -1) "</UL>\n") |
|
1032 | main_entries (t::ts) curdir = |
|
1033 let |
|
1034 val (name, path) = take_prefix (not_equal " ") (explode t); |
|
1035 |
|
1036 val tname = implode name |
|
1037 val tpath = |
|
1038 tack_on (relative_path (!chart00_path) (implode (tl path))) |
|
1039 tname; |
|
1040 val subdir = space_explode "/" |
|
1041 (relative_path base_path (implode (tl path))); |
|
1042 val level_diff = length subdir - length curdir; |
|
1043 in "\n" ^ |
|
1044 (if subdir <> curdir then |
|
1045 (implode (if level_diff > 0 then |
|
1046 replicate level_diff "<UL>\n" |
|
1047 else if level_diff < 0 then |
|
1048 replicate (~level_diff) "</UL>\n" |
|
1049 else []) ^ |
|
1050 "<H3>" ^ space_implode "/" subdir ^ "</H3>\n") |
|
1051 else "") ^ |
|
1052 "<A HREF = \"" ^ tpath ^ "_sub.html\"><IMG SRC = \"" ^ |
|
1053 tack_on gif_path "red_arrow.gif\" ALT = \\/></A>" ^ |
|
1054 "<A HREF = \"" ^ tpath ^ "_sup.html\"><IMG SRC = \"" ^ |
|
1055 tack_on gif_path "blue_arrow.gif\ |
|
1056 \\" ALT = /\\></A> <A HREF = \"" ^ tpath ^ |
|
1057 ".html\">" ^ tname ^ "</A><BR>\n" ^ |
|
1058 main_entries ts subdir |
|
1059 end; |
|
1060 |
|
1061 val out = open_out (tack_on (!chart00_path) "00-chart.html"); |
|
1062 val subdir = relative_path base_path (!chart00_path); |
|
1063 in output (out, |
|
1064 "<HTML><HEAD><TITLE>Isabelle/" ^ subdir ^ "</TITLE></HEAD>\n\ |
|
1065 \<H2>Isabelle/" ^ subdir ^ "</H2>\n\ |
|
1066 \The name of every theory is linked to its theory file<BR>\n\ |
|
1067 \<IMG SRC = \"" ^ tack_on gif_path "red_arrow.gif\ |
|
1068 \\" ALT = \\/></A> stands for subtheories (child theories)<BR>\n\ |
|
1069 \<IMG SRC = \"" ^ tack_on gif_path "blue_arrow.gif\ |
|
1070 \\" ALT = /\\></A> stands for supertheories (parent theories)\n\ |
|
1071 \<P><A HREF = \"" ^ |
|
1072 tack_on (relative_path (!chart00_path) base_path) "logics.html\">\ |
|
1073 \Back</A> to the index of Isabelle logics.\n<HR>" ^ |
|
1074 main_entries theories (space_explode "/" base_path) ^ |
|
1075 "</BODY></HTML>\n"); |
|
1076 close_out out |
|
1077 end; |
680 end; |
1078 end; |