90 (* thy database *) |
90 (* thy database *) |
91 |
91 |
92 type master = (Path.T * File.ident) * (Path.T * File.ident) option; |
92 type master = (Path.T * File.ident) * (Path.T * File.ident) option; |
93 |
93 |
94 type deps = |
94 type deps = |
95 {outdated: bool, (*entry considered outdated*) |
95 {update_time: int, (*symbolic time of last update; < 0 means outdated*) |
96 master: master option, (*master dependencies for thy + attached ML file*) |
96 master: master option, (*master dependencies for thy + attached ML file*) |
97 text: string list, (*source text for thy*) |
97 text: string list, (*source text for thy*) |
98 parents: string list, (*source specification of parents (partially qualified)*) |
98 parents: string list, (*source specification of parents (partially qualified)*) |
99 files: (*auxiliary files: source path, physical path + identifier*) |
99 files: (*auxiliary files: source path, physical path + identifier*) |
100 (Path.T * (Path.T * File.ident) option) list}; |
100 (Path.T * (Path.T * File.ident) option) list}; |
101 |
101 |
102 fun make_deps outdated master text parents files : deps = |
102 fun make_deps update_time master text parents files : deps = |
103 {outdated = outdated, master = master, text = text, parents = parents, files = files}; |
103 {update_time = update_time, master = master, text = text, parents = parents, files = files}; |
104 |
104 |
105 fun init_deps master text parents files = |
105 fun init_deps master text parents files = |
106 SOME (make_deps true master text parents (map (rpair NONE) files)); |
106 SOME (make_deps ~1 master text parents (map (rpair NONE) files)); |
107 |
107 |
108 fun master_idents (NONE: master option) = [] |
108 fun master_idents (NONE: master option) = [] |
109 | master_idents (SOME ((_, thy_id), NONE)) = [thy_id] |
109 | master_idents (SOME ((_, thy_id), NONE)) = [thy_id] |
110 | master_idents (SOME ((_, thy_id), SOME (_, ml_id))) = [thy_id, ml_id]; |
110 | master_idents (SOME ((_, thy_id), SOME (_, ml_id))) = [thy_id, ml_id]; |
111 |
111 |
233 else warning (loader_msg "unresolved dependencies of theory" [name] ^ |
233 else warning (loader_msg "unresolved dependencies of theory" [name] ^ |
234 " on file(s): " ^ commas_quote missing_files); |
234 " on file(s): " ^ commas_quote missing_files); |
235 in files end; |
235 in files end; |
236 |
236 |
237 |
237 |
238 (* maintain 'outdated' flag *) |
238 (* maintain update_time *) |
239 |
239 |
240 local |
240 local |
241 |
241 |
242 fun is_outdated name = |
242 fun is_outdated name = |
243 (case lookup_deps name of |
243 (case lookup_deps name of |
244 SOME (SOME {outdated, ...}) => outdated |
244 SOME (SOME {update_time, ...}) => update_time < 0 |
245 | _ => false); |
245 | _ => false); |
246 |
246 |
247 fun outdate_thy name = |
247 fun outdate_thy name = |
248 if is_finished name orelse is_outdated name then () |
248 if is_finished name orelse is_outdated name then () |
249 else CRITICAL (fn () => |
249 else CRITICAL (fn () => |
250 (change_deps name (Option.map (fn {outdated = _, master, text, parents, files} => |
250 (change_deps name (Option.map (fn {master, text, parents, files, ...} => |
251 make_deps true master text parents files)); perform Outdate name)); |
251 make_deps ~1 master text parents files)); perform Outdate name)); |
252 |
252 |
253 fun check_unfinished name = |
253 fun check_unfinished name = |
254 if is_finished name then (warning (loader_msg "tried to touch finished theory" [name]); NONE) |
254 if is_finished name then (warning (loader_msg "tried to touch finished theory" [name]); NONE) |
255 else SOME name; |
255 else SOME name; |
256 |
256 |
269 |
269 |
270 (* load_file *) |
270 (* load_file *) |
271 |
271 |
272 local |
272 local |
273 |
273 |
274 fun provide path name info (deps as SOME {outdated, master, text, parents, files}) = |
274 fun provide path name info (deps as SOME {update_time, master, text, parents, files}) = |
275 (if AList.defined (op =) files path then () |
275 (if AList.defined (op =) files path then () |
276 else warning (loader_msg "undeclared dependency of theory" [name] ^ |
276 else warning (loader_msg "undeclared dependency of theory" [name] ^ |
277 " on file: " ^ quote (Path.implode path)); |
277 " on file: " ^ quote (Path.implode path)); |
278 SOME (make_deps outdated master text parents (AList.update (op =) (path, SOME info) files))) |
278 SOME (make_deps update_time master text parents |
|
279 (AList.update (op =) (path, SOME info) files))) |
279 | provide _ _ _ NONE = NONE; |
280 | provide _ _ _ NONE = NONE; |
280 |
281 |
281 fun run_file path = |
282 fun run_file path = |
282 (case Option.map (Context.theory_name o Context.the_theory) (ML_Context.get_context ()) of |
283 (case Option.map (Context.theory_name o Context.the_theory) (ML_Context.get_context ()) of |
283 NONE => (ThyLoad.load_ml Path.current path; ()) |
284 NONE => (ThyLoad.load_ml Path.current path; ()) |
308 (* load_thy *) |
309 (* load_thy *) |
309 |
310 |
310 fun required_by _ [] = "" |
311 fun required_by _ [] = "" |
311 | required_by s initiators = s ^ "(required by " ^ show_path (rev initiators) ^ ")"; |
312 | required_by s initiators = s ^ "(required by " ^ show_path (rev initiators) ^ ")"; |
312 |
313 |
313 fun load_thy ml time initiators dir name = |
314 fun load_thy ml time upd_time initiators dir name = |
314 let |
315 let |
315 val _ = priority ("Loading theory " ^ quote name ^ required_by " " initiators); |
316 val _ = priority ("Loading theory " ^ quote name ^ required_by " " initiators); |
316 val (pos, text, files) = |
317 val (pos, text, files) = |
317 (case get_deps name of |
318 (case get_deps name of |
318 SOME {master = SOME ((master_path, _), _), text, files, ...} => |
319 SOME {master = SOME ((master_path, _), _), text, files, ...} => |
319 (Position.path master_path, text, files) |
320 (Position.path master_path, text, files) |
320 | _ => error (loader_msg "corrupted dependency information" [name])); |
321 | _ => error (loader_msg "corrupted dependency information" [name])); |
321 val _ = touch_thy name; |
322 val _ = touch_thy name; |
|
323 val _ = CRITICAL (fn () => |
|
324 change_deps name (Option.map (fn {master, text, parents, files, ...} => |
|
325 make_deps upd_time master text parents files))); |
322 val _ = ThyLoad.load_thy dir name pos text ml (time orelse ! Output.timing); |
326 val _ = ThyLoad.load_thy dir name pos text ml (time orelse ! Output.timing); |
323 val _ = check_files name; |
327 val _ = check_files name; |
324 in |
328 in |
325 CRITICAL (fn () => |
329 CRITICAL (fn () => |
326 (change_deps name |
330 (change_deps name |
327 (Option.map (fn {master, parents, files, ...} => make_deps false master [] parents files)); |
331 (Option.map (fn {update_time, master, parents, files, ...} => |
|
332 make_deps update_time master [] parents files)); |
328 perform Update name)) |
333 perform Update name)) |
329 end; |
334 end; |
330 |
335 |
331 |
336 |
332 (* require_thy -- checking database entries wrt. the file-system *) |
337 (* require_thy -- checking database entries wrt. the file-system *) |
345 (case lookup_deps name of |
350 (case lookup_deps name of |
346 SOME NONE => (true, NONE, get_parents name) |
351 SOME NONE => (true, NONE, get_parents name) |
347 | NONE => |
352 | NONE => |
348 let val {master, text, imports = parents, uses = files} = ThyLoad.deps_thy dir name ml |
353 let val {master, text, imports = parents, uses = files} = ThyLoad.deps_thy dir name ml |
349 in (false, init_deps (SOME master) text parents files, parents) end |
354 in (false, init_deps (SOME master) text parents files, parents) end |
350 | SOME (deps as SOME {outdated, master, text, parents, files}) => |
355 | SOME (deps as SOME {update_time, master, text, parents, files}) => |
351 if not strict andalso can get_theory name then (true, deps, parents) |
356 if not strict andalso can get_theory name then (true, deps, parents) |
352 else |
357 else |
353 let val master' = SOME (ThyLoad.check_thy dir name ml) in |
358 let val master' = SOME (ThyLoad.check_thy dir name ml) in |
354 if master_idents master <> master_idents master' |
359 if master_idents master <> master_idents master' |
355 then |
360 then |
357 ThyLoad.deps_thy dir name ml; |
362 ThyLoad.deps_thy dir name ml; |
358 in (false, init_deps master' text' parents' files', parents') end |
363 in (false, init_deps master' text' parents' files', parents') end |
359 else |
364 else |
360 let |
365 let |
361 val checked_files = map (check_ml master') files; |
366 val checked_files = map (check_ml master') files; |
362 val current = not outdated andalso forall (is_some o snd) checked_files; |
367 val current = update_time >= 0 andalso forall (is_some o snd) checked_files; |
363 val deps' = SOME (make_deps (not current) master' text parents checked_files); |
368 val update_time' = if current then update_time else ~1; |
|
369 val deps' = SOME (make_deps update_time' master' text parents checked_files); |
364 in (current, deps', parents) end |
370 in (current, deps', parents) end |
365 end); |
371 end); |
366 |
372 |
367 in |
373 in |
368 |
374 |
389 val (parents_current, (tasks_graph', tasks_len')) = |
395 val (parents_current, (tasks_graph', tasks_len')) = |
390 require_thys true time (strict andalso keep_strict) keep_strict |
396 require_thys true time (strict andalso keep_strict) keep_strict |
391 (name :: initiators) (Path.append dir (master_dir' deps)) parents tasks; |
397 (name :: initiators) (Path.append dir (master_dir' deps)) parents tasks; |
392 |
398 |
393 val all_current = current andalso parents_current; |
399 val all_current = current andalso parents_current; |
394 val thy = if all_current then SOME (get_theory name) else NONE; |
400 val theory = if all_current then SOME (get_theory name) else NONE; |
395 val _ = change_thys (new_deps name parent_names (deps, thy)); |
401 val _ = change_thys (new_deps name parent_names (deps, theory)); |
396 |
402 |
|
403 val upd_time = serial (); |
397 val tasks_graph'' = tasks_graph' |> new_deps name parent_names |
404 val tasks_graph'' = tasks_graph' |> new_deps name parent_names |
398 (if all_current then Task.Finished |
405 (if all_current then Task.Finished |
399 else Task.Task (fn () => load_thy ml time initiators dir' name)); |
406 else Task.Task (fn () => load_thy ml time upd_time initiators dir' name)); |
400 val tasks_len'' = if all_current then tasks_len' else tasks_len' + 1; |
407 val tasks_len'' = if all_current then tasks_len' else tasks_len' + 1; |
401 in (all_current, (tasks_graph'', tasks_len'')) end) |
408 in (all_current, (tasks_graph'', tasks_len'')) end) |
402 end; |
409 end; |
403 |
410 |
404 end; |
411 end; |
418 | max_task _ task' = task'; |
425 | max_task _ task' = task'; |
419 |
426 |
420 fun next_task G = |
427 fun next_task G = |
421 let |
428 let |
422 val tasks = Graph.minimals G |> map (fn name => |
429 val tasks = Graph.minimals G |> map (fn name => |
423 (name, (Graph.get_node G name, length (Graph.imm_succs G name)))) |
430 (name, (Graph.get_node G name, length (Graph.imm_succs G name)))); |
424 val finished = filter (Task.is_finished o fst o snd) tasks; |
431 val finished = filter (Task.is_finished o fst o snd) tasks; |
425 in |
432 in |
426 if not (null finished) then next_task (Graph.del_nodes (map fst finished) G) |
433 if not (null finished) then next_task (Graph.del_nodes (map fst finished) G) |
427 else if null tasks then ((Task.Finished, I), G) |
434 else if null tasks then ((Task.Finished, I), G) |
428 else |
435 else |
496 (* FIXME tmp *) |
503 (* FIXME tmp *) |
497 val _ = CRITICAL (fn () => |
504 val _ = CRITICAL (fn () => |
498 ML_Context.set_context (SOME (Context.Theory (get_theory (List.last parent_names))))); |
505 ML_Context.set_context (SOME (Context.Theory (get_theory (List.last parent_names))))); |
499 val _ = check_uses name uses; |
506 val _ = check_uses name uses; |
500 |
507 |
501 val theory = |
508 val theory = Theory.begin_theory name (map get_theory parent_names); |
502 Theory.begin_theory name (map get_theory parent_names) |
|
503 |> Present.begin_theory dir uses; |
|
504 |
509 |
505 val deps = |
510 val deps = |
506 if known_thy name then get_deps name |
511 if known_thy name then get_deps name |
507 else init_deps NONE [] parents (map #1 uses); |
512 else init_deps NONE [] parents (map #1 uses); |
508 val _ = change_thys (new_deps name parent_names (deps, NONE)); |
513 val _ = change_thys (new_deps name parent_names (deps, NONE)); |
509 |
514 |
|
515 val update_time = (case deps of NONE => 0 | SOME {update_time, ...} => update_time); |
|
516 val theory' = Present.begin_theory update_time dir uses theory; |
|
517 |
510 val uses_now = map_filter (fn (x, true) => SOME x | _ => NONE) uses; |
518 val uses_now = map_filter (fn (x, true) => SOME x | _ => NONE) uses; |
511 val ((), theory') = |
519 val ((), theory'') = |
512 ML_Context.pass_context (Context.Theory theory) (List.app (load_file false)) uses_now |
520 ML_Context.pass_context (Context.Theory theory') (List.app (load_file false)) uses_now |
513 ||> Context.the_theory; |
521 ||> Context.the_theory; |
514 in theory' end; |
522 in theory'' end; |
515 |
523 |
516 fun end_theory theory = |
524 fun end_theory theory = |
517 let |
525 let |
518 val name = Context.theory_name theory; |
526 val name = Context.theory_name theory; |
519 val theory' = Theory.end_theory theory; |
527 val theory' = Theory.end_theory theory; |
530 val _ = map get_theory (get_parents name); |
538 val _ = map get_theory (get_parents name); |
531 val _ = check_unfinished error name; |
539 val _ = check_unfinished error name; |
532 val _ = touch_thy name; |
540 val _ = touch_thy name; |
533 val files = check_files name; |
541 val files = check_files name; |
534 val master = #master (ThyLoad.deps_thy Path.current name false); |
542 val master = #master (ThyLoad.deps_thy Path.current name false); |
|
543 val upd_time = serial (); |
535 in |
544 in |
536 CRITICAL (fn () => |
545 CRITICAL (fn () => |
537 (change_deps name |
546 (change_deps name |
538 (Option.map (fn {parents, ...} => make_deps false (SOME master) [] parents files)); |
547 (Option.map (fn {parents, ...} => make_deps upd_time (SOME master) [] parents files)); |
539 perform Update name)) |
548 perform Update name)) |
540 end; |
549 end; |
541 |
550 |
542 fun register_theory theory = |
551 fun register_theory theory = |
543 let |
552 let |