2 ID: $Id$ |
2 ID: $Id$ |
3 Author: Carsten Clasohm and Markus Wenzel and Sonia Mahjoub and |
3 Author: Carsten Clasohm and Markus Wenzel and Sonia Mahjoub and |
4 Tobias Nipkow and L C Paulson |
4 Tobias Nipkow and L C Paulson |
5 Copyright 1994 TU Muenchen |
5 Copyright 1994 TU Muenchen |
6 |
6 |
7 Functions for reading theory files, and storing and retrieving theories |
7 Functions for reading theory files, and storing and retrieving theories, |
8 and theorems. |
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 = ThyInfo of {path: string, |
13 children: string list, |
13 children: string list, |
14 thy_time: string option, |
14 thy_time: string option, |
15 ml_time: string option, |
15 ml_time: string option, |
16 theory: theory option, |
16 theory: theory option, |
17 thms: thm Symtab.table}; |
17 thms: thm Symtab.table, |
|
18 thy_simps: thm list, ml_simps: thm list}; |
18 (*meaning of special values: |
19 (*meaning of special values: |
19 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 |
20 = Some "" theory was read but has either been marked |
21 = Some "" theory was read but has either been marked |
21 as outdated or there is no such file for |
22 as outdated or there is no such file for |
22 this theory (see e.g. 'virtual' theories |
23 this theory (see e.g. 'virtual' theories |
53 val thms_of: theory -> (string * thm) list |
54 val thms_of: theory -> (string * thm) list |
54 val print_theory: theory -> unit |
55 val print_theory: theory -> unit |
55 end; |
56 end; |
56 |
57 |
57 |
58 |
58 functor ReadthyFUN(structure ThySyn: THY_SYN and ThmDB: THMDB): READTHY = |
59 functor ReadthyFUN(structure ThySyn: THY_SYN and ThmDB: THMDB |
|
60 and Simplifier: SIMPLIFIER): READTHY = |
59 struct |
61 struct |
60 local open ThmDB in |
62 |
|
63 open ThmDB Simplifier; |
61 |
64 |
62 datatype basetype = Thy of string |
65 datatype basetype = Thy of string |
63 | File of string; |
66 | File of string; |
64 |
67 |
65 val loaded_thys = ref (Symtab.make [("ProtoPure", |
68 val loaded_thys = ref (Symtab.make [("ProtoPure", |
66 ThyInfo {path = "", |
69 ThyInfo {path = "", |
67 children = ["Pure", "CPure"], |
70 children = ["Pure", "CPure"], |
68 thy_time = Some "", ml_time = Some "", |
71 thy_time = Some "", ml_time = Some "", |
69 theory = Some proto_pure_thy, |
72 theory = Some proto_pure_thy, |
70 thms = Symtab.null}), |
73 thms = Symtab.null, |
|
74 thy_simps = [], ml_simps = []}), |
71 ("Pure", ThyInfo {path = "", children = [], |
75 ("Pure", ThyInfo {path = "", children = [], |
72 thy_time = Some "", ml_time = Some "", |
76 thy_time = Some "", ml_time = Some "", |
73 theory = Some pure_thy, |
77 theory = Some pure_thy, |
74 thms = Symtab.null}), |
78 thms = Symtab.null, |
|
79 thy_simps = [], ml_simps = []}), |
75 ("CPure", ThyInfo {path = "", |
80 ("CPure", ThyInfo {path = "", |
76 children = [], |
81 children = [], |
77 thy_time = Some "", ml_time = Some "", |
82 thy_time = Some "", ml_time = Some "", |
78 theory = Some cpure_thy, |
83 theory = Some cpure_thy, |
79 thms = Symtab.null})]); |
84 thms = Symtab.null, |
|
85 thy_simps = [], ml_simps = []})]); |
80 |
86 |
81 val loadpath = ref ["."]; (*default search path for theory files *) |
87 val loadpath = ref ["."]; (*default search path for theory files *) |
82 |
88 |
83 val delete_tmpfiles = ref true; (*remove temporary files after use *) |
89 val delete_tmpfiles = ref true; (*remove temporary files after use *) |
84 |
90 |
187 else new_filename () |
210 else new_filename () |
188 end; |
211 end; |
189 |
212 |
190 (*Remove theory from all child lists in loaded_thys *) |
213 (*Remove theory from all child lists in loaded_thys *) |
191 fun unlink_thy tname = |
214 fun unlink_thy tname = |
192 let fun remove (ThyInfo {path, children, thy_time, ml_time, theory, thms}) = |
215 let fun remove (ThyInfo {path, children, thy_time, ml_time, theory, thms, |
|
216 thy_simps, ml_simps}) = |
193 ThyInfo {path = path, children = children \ tname, |
217 ThyInfo {path = path, children = children \ tname, |
194 thy_time = thy_time, ml_time = ml_time, |
218 thy_time = thy_time, ml_time = ml_time, theory = theory, |
195 theory = theory, thms = thms} |
219 thms = thms, thy_simps = thy_simps, ml_simps = ml_simps} |
196 in loaded_thys := Symtab.map remove (!loaded_thys) end; |
220 in loaded_thys := Symtab.map remove (!loaded_thys) end; |
197 |
221 |
198 (*Remove a theory from loaded_thys *) |
222 (*Remove a theory from loaded_thys *) |
199 fun remove_thy tname = |
223 fun remove_thy tname = |
200 loaded_thys := Symtab.make (filter_out (fn (id, _) => id = tname) |
224 loaded_thys := Symtab.make (filter_out (fn (id, _) => id = tname) |
201 (Symtab.dest (!loaded_thys))); |
225 (Symtab.dest (!loaded_thys))); |
202 |
226 |
203 (*Change thy_time and ml_time for an existent item *) |
227 (*Change thy_time and ml_time for an existent item *) |
204 fun set_info thy_time ml_time tname = |
228 fun set_info thy_time ml_time tname = |
205 let val ThyInfo {path, children, theory, thms, ...} = |
229 let val ThyInfo {path, children, theory, thms, thy_simps, ml_simps, ...} = |
206 the (Symtab.lookup (!loaded_thys, tname)); |
230 the (Symtab.lookup (!loaded_thys, tname)); |
207 in loaded_thys := Symtab.update ((tname, |
231 in loaded_thys := Symtab.update |
208 ThyInfo {path = path, children = children, |
232 ((tname, |
209 thy_time = thy_time, ml_time = ml_time, |
233 ThyInfo {path = path, children = children, thy_time = thy_time, |
210 theory = theory, thms = thms}), !loaded_thys) |
234 ml_time = ml_time, theory = theory, thms = thms, |
|
235 thy_simps = thy_simps, ml_simps = ml_simps}), |
|
236 !loaded_thys) |
211 end; |
237 end; |
212 |
238 |
213 (*Mark theory as changed since last read if it has been completly read *) |
239 (*Mark theory as changed since last read if it has been completly read *) |
214 fun mark_outdated tname = |
240 fun mark_outdated tname = |
215 let val t = get_thyinfo tname; |
241 let val t = get_thyinfo tname; |
225 they were last read; |
251 they were last read; |
226 loaded_thys is a thy_info list ref containing all theories that have |
252 loaded_thys is a thy_info list ref containing all theories that have |
227 completly been read by this and preceeding use_thy calls. |
253 completly been read by this and preceeding use_thy calls. |
228 If a theory changed since its last use its children are marked as changed *) |
254 If a theory changed since its last use its children are marked as changed *) |
229 fun use_thy name = |
255 fun use_thy name = |
230 let val (path, tname) = split_filename name; |
256 let |
231 val (thy_file, ml_file) = get_filenames path tname; |
257 val (path, tname) = split_filename name; |
232 val (abs_path, _) = if thy_file = "" then split_filename ml_file |
258 val (thy_file, ml_file) = get_filenames path tname; |
233 else split_filename thy_file; |
259 val (abs_path, _) = if thy_file = "" then split_filename ml_file |
234 val (thy_uptodate, ml_uptodate) = thy_unchanged tname |
260 else split_filename thy_file; |
235 thy_file ml_file; |
261 val (thy_uptodate, ml_uptodate) = thy_unchanged tname thy_file ml_file; |
236 |
262 val (thy_simps, ml_simps) = get_simps tname; |
237 (*Set absolute path for loaded theory *) |
263 val old_simps = ref []; |
238 fun set_path () = |
264 |
239 let val ThyInfo {children, thy_time, ml_time, theory, thms, ...} = |
265 (*Set absolute path for loaded theory *) |
240 the (Symtab.lookup (!loaded_thys, tname)); |
266 fun set_path () = |
241 in loaded_thys := Symtab.update ((tname, |
267 let val ThyInfo {children, thy_time, ml_time, theory, thms, |
242 ThyInfo {path = abs_path, children = children, |
268 thy_simps, ml_simps, ...} = |
243 thy_time = thy_time, ml_time = ml_time, |
269 the (Symtab.lookup (!loaded_thys, tname)); |
244 theory = theory, thms = thms}), |
270 in loaded_thys := Symtab.update ((tname, |
245 !loaded_thys) |
271 ThyInfo {path = abs_path, children = children, |
246 end; |
272 thy_time = thy_time, ml_time = ml_time, |
247 |
273 theory = theory, thms = thms, |
248 (*Mark all direct descendants of a theory as changed *) |
274 thy_simps = thy_simps, |
249 fun mark_children thy = |
275 ml_simps = ml_simps}), |
250 let val ThyInfo {children, ...} = the (get_thyinfo thy); |
276 !loaded_thys) |
251 val present = filter (is_some o get_thyinfo) children; |
277 end; |
252 val loaded = filter already_loaded present; |
278 |
253 in if loaded <> [] then |
279 (*Mark all direct descendants of a theory as changed *) |
254 writeln ("The following children of theory " ^ (quote thy) |
280 fun mark_children thy = |
255 ^ " are now out-of-date: " |
281 let val ThyInfo {children, ...} = the (get_thyinfo thy); |
256 ^ (quote (space_implode "\",\"" loaded))) |
282 val present = filter (is_some o get_thyinfo) children; |
257 else (); |
283 val loaded = filter already_loaded present; |
258 seq mark_outdated present |
284 in if loaded <> [] then |
259 end; |
285 writeln ("The following children of theory " ^ (quote thy) |
260 |
286 ^ " are now out-of-date: " |
261 (*Remove all theorems associated with a theory*) |
287 ^ (quote (space_implode "\",\"" loaded))) |
262 fun delete_thms () = |
288 else (); |
263 let val tinfo = case Symtab.lookup (!loaded_thys, tname) of |
289 seq mark_outdated present |
264 Some (ThyInfo {path, children, thy_time, ml_time, theory, ...}) => |
290 end; |
265 ThyInfo {path = path, children = children, |
291 |
266 thy_time = thy_time, ml_time = ml_time, |
292 (*Remove theorems associated with a theory*) |
267 theory = theory, thms = Symtab.null} |
293 fun delete_thms () = |
268 | None => ThyInfo {path = "", children = [], |
294 let |
269 thy_time = None, ml_time = None, |
295 val tinfo = case get_thyinfo tname of |
270 theory = None, thms = Symtab.null}; |
296 Some (ThyInfo {path, children, thy_time, ml_time, theory, |
271 in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys) end; |
297 thy_simps, ml_simps, ...}) => |
272 in if thy_uptodate andalso ml_uptodate then () |
298 ThyInfo {path = path, children = children, |
|
299 thy_time = thy_time, ml_time = ml_time, |
|
300 theory = theory, thms = Symtab.null, |
|
301 thy_simps = thy_simps, ml_simps = ml_simps} |
|
302 | None => ThyInfo {path = "", children = [], |
|
303 thy_time = None, ml_time = None, |
|
304 theory = None, thms = Symtab.null, |
|
305 thy_simps = [], ml_simps = []}; |
|
306 in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys) end; |
|
307 |
|
308 fun update_simps (new_thy_simps, new_ml_simps) = |
|
309 let val ThyInfo {path, children, thy_time, ml_time, theory, thms, |
|
310 thy_simps, ml_simps} = the (get_thyinfo tname); |
|
311 |
|
312 val (thy_simps', ml_simps') = |
|
313 (if is_none new_thy_simps then thy_simps else the new_thy_simps, |
|
314 if is_none new_ml_simps then ml_simps else the new_ml_simps); |
|
315 in loaded_thys := Symtab.update ((tname, |
|
316 ThyInfo {path = path, children = children, |
|
317 thy_time = thy_time, ml_time = ml_time, theory = theory, |
|
318 thms = thms, thy_simps = thy_simps', |
|
319 ml_simps = ml_simps'}), !loaded_thys) |
|
320 end; |
|
321 |
|
322 in if thy_uptodate andalso ml_uptodate then () |
|
323 else |
|
324 ( |
|
325 delete_thms (); |
|
326 |
|
327 if thy_uptodate orelse thy_file = "" then |
|
328 (Delsimps ml_simps; |
|
329 old_simps := #simps(rep_ss (!simpset)); |
|
330 update_simps (None, Some [])) |
273 else |
331 else |
274 ( |
332 (writeln ("Reading \"" ^ name ^ ".thy\""); |
275 delete_thms (); |
333 Delsimps (thy_simps @ ml_simps); |
276 |
334 old_simps := #simps(rep_ss (!simpset)); |
277 if thy_uptodate orelse thy_file = "" then () |
335 update_simps (Some [], Some []); (*clear simp lists in case use_thy |
278 else (writeln ("Reading \"" ^ name ^ ".thy\""); |
336 encounters an EROR exception*) |
279 read_thy tname thy_file; |
337 read_thy tname thy_file; |
280 use (out_name tname); |
338 use (out_name tname); |
281 |
339 |
282 if not (!delete_tmpfiles) then () |
340 if not (!delete_tmpfiles) then () |
283 else delete_file (out_name tname) |
341 else delete_file (out_name tname); |
284 ); |
342 |
285 set_info (Some (file_info thy_file)) None tname; |
343 update_simps |
|
344 (Some (gen_rems same_thm (#simps(rep_ss (!simpset)), !old_simps)), |
|
345 None); |
|
346 old_simps := #simps(rep_ss (!simpset)) |
|
347 ); |
|
348 |
|
349 set_info (Some (file_info thy_file)) None tname; |
286 (*mark thy_file as successfully loaded*) |
350 (*mark thy_file as successfully loaded*) |
287 |
351 |
288 if ml_file = "" then () |
352 if ml_file = "" then () |
289 else (writeln ("Reading \"" ^ name ^ ".ML\""); |
353 else |
290 use ml_file); |
354 (writeln ("Reading \"" ^ name ^ ".ML\""); |
291 |
355 use ml_file; |
292 use_string |
356 |
293 ["val _ = (store_theory (" ^ tname ^ ".thy, " ^ quote tname ^ ");\ |
357 update_simps (None, |
294 \map store_thm_db (axioms_of " ^ tname ^ ".thy));"]; |
358 Some (gen_rems same_thm (#simps(rep_ss (!simpset)), !old_simps))) |
295 (*Store theory again because it could have been redefined*) |
359 ); |
296 |
360 |
297 (*Now set the correct info*) |
361 (*Store theory again because it could have been redefined*) |
298 set_info (Some (file_info thy_file)) (Some (file_info ml_file)) tname; |
362 use_string |
299 set_path (); |
363 ["val _ = (store_theory (" ^ tname ^ ".thy, " ^ quote tname ^ "); " ^ |
300 |
364 |
301 (*Mark theories that have to be reloaded*) |
365 (*Store new axioms in theorem database; ignore theories which are just |
302 mark_children tname |
366 copies of existing ones*) |
303 ) |
367 let val parents = get_parents tname; |
304 end; |
368 val fst_thy = get_theory (hd parents); |
|
369 val this_thy = get_theory tname; |
|
370 in if length parents = 1 |
|
371 andalso Sign.eq_sg (sign_of fst_thy, sign_of this_thy) then "" |
|
372 else |
|
373 "map store_thm_db (axioms_of " ^ tname ^ ".thy));" |
|
374 end]; |
|
375 |
|
376 (*Now set the correct info*) |
|
377 set_info (Some (file_info thy_file)) (Some (file_info ml_file)) tname; |
|
378 set_path (); |
|
379 |
|
380 (*Mark theories that have to be reloaded*) |
|
381 mark_children tname |
|
382 ) |
|
383 end; |
305 |
384 |
306 fun time_use_thy tname = timeit(fn()=> |
385 fun time_use_thy tname = timeit(fn()=> |
307 (writeln("\n**** Starting Theory " ^ tname ^ " ****"); |
386 (writeln("\n**** Starting Theory " ^ tname ^ " ****"); |
308 use_thy tname; |
387 use_thy tname; |
309 writeln("\n**** Finished Theory " ^ tname ^ " ****")) |
388 writeln("\n**** Finished Theory " ^ tname ^ " ****")) |
398 (*Add child to child list of base *) |
477 (*Add child to child list of base *) |
399 fun add_child base = |
478 fun add_child base = |
400 let val tinfo = |
479 let val tinfo = |
401 case Symtab.lookup (!loaded_thys, base) of |
480 case Symtab.lookup (!loaded_thys, base) of |
402 Some (ThyInfo {path, children, thy_time, ml_time, |
481 Some (ThyInfo {path, children, thy_time, ml_time, |
403 theory, thms}) => |
482 theory, thms, thy_simps, ml_simps}) => |
404 ThyInfo {path = path, children = child ins children, |
483 ThyInfo {path = path, children = child ins children, |
405 thy_time = thy_time, ml_time = ml_time, |
484 thy_time = thy_time, ml_time = ml_time, |
406 theory = theory, thms = thms} |
485 theory = theory, thms = thms, |
|
486 thy_simps = thy_simps, ml_simps = ml_simps} |
407 | None => ThyInfo {path = "", children = [child], |
487 | None => ThyInfo {path = "", children = [child], |
408 thy_time = None, ml_time = None, |
488 thy_time = None, ml_time = None, |
409 theory = None, thms = Symtab.null}; |
489 theory = None, thms = Symtab.null, |
|
490 thy_simps = [], ml_simps = []}; |
410 in loaded_thys := Symtab.update ((base, tinfo), !loaded_thys) end; |
491 in loaded_thys := Symtab.update ((base, tinfo), !loaded_thys) end; |
411 |
492 |
412 (*Load a base theory if not already done |
493 (*Load a base theory if not already done |
413 and no cycle would be created *) |
494 and no cycle would be created *) |
414 fun load base = |
495 fun load base = |
435 | load_base (File b :: bs) = |
516 | load_base (File b :: bs) = |
436 (load b; |
517 (load b; |
437 load_base bs) (*don't add it to mergelist *) |
518 load_base bs) (*don't add it to mergelist *) |
438 | load_base [] = []; |
519 | load_base [] = []; |
439 |
520 |
440 (*Get theory object for a loaded theory *) |
|
441 fun get_theory name = |
|
442 let val ThyInfo {theory, ...} = the (get_thyinfo name) |
|
443 in the theory end; |
|
444 |
|
445 val mergelist = (unlink_thy child; |
521 val mergelist = (unlink_thy child; |
446 load_base bases); |
522 load_base bases); |
447 in writeln ("Loading theory " ^ (quote child)); |
523 in writeln ("Loading theory " ^ (quote child)); |
448 merge_thy_list mk_draft (map get_theory mergelist) end; |
524 merge_thy_list mk_draft (map get_theory mergelist) end; |
449 |
525 |
450 (*Change theory object for an existent item of loaded_thys |
526 (*Change theory object for an existent item of loaded_thys |
451 or create a new item; also store axioms in Thm database*) |
527 or create a new item; also store axioms in Thm database*) |
452 fun store_theory (thy, tname) = |
528 fun store_theory (thy, tname) = |
453 let val tinfo = case Symtab.lookup (!loaded_thys, tname) of |
529 let val tinfo = case Symtab.lookup (!loaded_thys, tname) of |
454 Some (ThyInfo {path, children, thy_time, ml_time, thms, ...}) => |
530 Some (ThyInfo {path, children, thy_time, ml_time, thms, |
|
531 thy_simps, ml_simps, ...}) => |
455 ThyInfo {path = path, children = children, |
532 ThyInfo {path = path, children = children, |
456 thy_time = thy_time, ml_time = ml_time, |
533 thy_time = thy_time, ml_time = ml_time, |
457 theory = Some thy, thms = thms} |
534 theory = Some thy, thms = thms, |
|
535 thy_simps = thy_simps, ml_simps = ml_simps} |
458 | None => ThyInfo {path = "", children = [], |
536 | None => ThyInfo {path = "", children = [], |
459 thy_time = None, ml_time = None, |
537 thy_time = None, ml_time = None, |
460 theory = Some thy, thms = Symtab.null}; |
538 theory = Some thy, thms = Symtab.null, |
|
539 thy_simps = [], ml_simps = []}; |
461 in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys) |
540 in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys) |
462 end; |
541 end; |
463 |
542 |
464 |
543 |
465 (** store and retrieve theorems **) |
544 (** store and retrieve theorems **) |
497 (* Store theorems *) |
576 (* Store theorems *) |
498 |
577 |
499 (*Store a theorem in the thy_info of its theory*) |
578 (*Store a theorem in the thy_info of its theory*) |
500 fun store_thm (name, thm) = |
579 fun store_thm (name, thm) = |
501 let |
580 let |
502 val (thy_name, ThyInfo {path, children, thy_time, ml_time, theory, thms}) = |
581 val (thy_name, ThyInfo {path, children, thy_time, ml_time, theory, thms, |
|
582 thy_simps, ml_simps}) = |
503 thyinfo_of_sign (#sign (rep_thm thm)); |
583 thyinfo_of_sign (#sign (rep_thm thm)); |
504 |
584 |
505 val thms' = Symtab.update_new ((name, thm), thms) |
585 val thms' = Symtab.update_new ((name, thm), thms) |
506 handle Symtab.DUPLICATE s => |
586 handle Symtab.DUPLICATE s => |
507 (if eq_thm (the (Symtab.lookup (thms, name)), thm) then |
587 (if same_thm (the (Symtab.lookup (thms, name)), thm) then |
508 (writeln ("Warning: Theory database already contains copy of\ |
588 (writeln ("Warning: Theory database already contains copy of\ |
509 \ theorem " ^ quote name); |
589 \ theorem " ^ quote name); |
510 thms) |
590 thms) |
511 else error ("Duplicate theorem name " ^ quote s |
591 else error ("Duplicate theorem name " ^ quote s |
512 ^ " used in theory database")); |
592 ^ " used in theory database")); |
513 in |
593 in |
514 loaded_thys := Symtab.update |
594 loaded_thys := Symtab.update |
515 ((thy_name, ThyInfo {path = path, children = children, |
595 ((thy_name, ThyInfo {path = path, children = children, |
516 thy_time = thy_time, ml_time = ml_time, theory = theory, thms = thms'}), |
596 thy_time = thy_time, ml_time = ml_time, |
517 ! loaded_thys); |
597 theory = theory, thms = thms', |
|
598 thy_simps = thy_simps, ml_simps = ml_simps}), |
|
599 !loaded_thys); |
518 store_thm_db (name, thm) |
600 store_thm_db (name, thm) |
519 end; |
601 end; |
520 |
602 |
521 (*Store result of proof in loaded_thys and as ML value*) |
603 (*Store result of proof in loaded_thys and as ML value*) |
522 |
604 |